You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过点击在Tkinter显示的PIL图像上绘制像素

在Tkinter中点击PIL图像绘制像素不显示的解决方法

我在Tkinter中显示PIL图像时,想要点击图像绘制像素。目前已经能获取点击的坐标,但绘制的像素无法在屏幕上显示。

原代码

class selectPoints(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)
        alto = int(master.alto)
        ancho = int(master.ancho)
        master.geometry(f'{ancho+50}x{alto+100}')
        canva = Image.new('RGB', (ancho, alto), (255, 255, 255))

        # 获取点击坐标的函数        
        def callback(event): 
            color = (0, 255, 0)
            canva.putpixel((event.x, event.y), color)
            print ("clicked at: ", event.x, event.y)
    
        tkpic = ImageTk.PhotoImage(canva)
        label = tk.Label(self, image=tkpic)
        label.image = tkpic  # 保存图像引用
        label.pack()
        label.bind("<Button-1>", callback)

尝试过的无效修改

我尝试每次点击时重新生成图像并创建新Label,但图像仍无变化:

def callback(event):
    color = (0, 255, 0)
    canva.putpixel((event.x, event.y), color)

    tkpic = ImageTk.PhotoImage(canva)
    label = tk.Label(self, image=tkpic)
    label.image = tkpic  # 保存图像引用
    
    print ("clicked at: ", event.x, event.y)

问题原因及解决方法

问题核心在于:

  1. 原代码中canva和label是__init__内的局部变量,修改canva后没有同步更新Label的显示内容;
  2. 无效修改中新建了Label但未替换原有Label,且未维护图像引用。

正确的做法是将canva和label设为类的实例变量,修改像素后直接更新原有Label的图像属性:

class selectPoints(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)
        alto = int(master.alto)
        ancho = int(master.ancho)
        master.geometry(f'{ancho+50}x{alto+100}')
        # 将画布设为实例变量
        self.canva = Image.new('RGB', (ancho, alto), (255, 255, 255))

        # 获取点击坐标的函数        
        def callback(event): 
            color = (0, 255, 0)
            self.canva.putpixel((event.x, event.y), color)
            # 重新生成图像
            updated_pic = ImageTk.PhotoImage(self.canva)
            # 更新已有Label的图像
            self.label.config(image=updated_pic)
            # 保存图像引用,避免被垃圾回收
            self.label.image = updated_pic
            print ("clicked at: ", event.x, event.y)
    
        initial_pic = ImageTk.PhotoImage(self.canva)
        # 将Label设为实例变量
        self.label = tk.Label(self, image=initial_pic)
        self.label.image = initial_pic  # 保存初始图像引用
        self.label.pack()
        self.label.bind("<Button-1>", callback)

关键说明

  • 使用self.xxx将画布和Label转为实例变量,确保嵌套函数callback能访问并修改它们;
  • 修改像素后重新生成PhotoImage,通过config()方法更新原有Label的图像,而不是新建Label;
  • 每次更新图像后都要重新保存self.label.image,防止Python垃圾回收机制回收图像对象,导致显示空白。

内容的提问来源于stack exchange,提问作者Coolhatena

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 15:10:58