如何更新 Tkinter 标签小部件的图像?

Posted

技术标签:

【中文标题】如何更新 Tkinter 标签小部件的图像?【英文标题】:How to update the image of a Tkinter Label widget? 【发布时间】:2011-03-29 18:23:41 【问题描述】:

我希望能够替换 Tkinter 标签上的图像,但我不知道该怎么做,除了替换小部件本身。

目前,我可以像这样显示图像:

import Tkinter as tk
import ImageTk

root = tk.Tk()
img = ImageTk.PhotoImage(Image.open(path))
panel = tk.Label(root, image = img)
panel.pack(side = "bottom", fill = "both", expand = "yes")
root.mainloop()

但是,当用户点击ENTER 键时,我想更改图像。

import Tkinter as tk
import ImageTk

root = tk.Tk()

img = ImageTk.PhotoImage(Image.open(path))
panel = tk.Label(root, image = img)
panel.pack(side = "bottom", fill = "both", expand = "yes")

def callback(e):
    # change image

root.bind("<Return>", callback)
root.mainloop()

这可能吗?

【问题讨论】:

【参考方案1】:

label.configure 方法在 panel.configure(image=img) 中确实有效。

我忘记做的是包含panel.image=img,以防止垃圾收集删除图像。

以下是新版本:

import Tkinter as tk
import ImageTk


root = tk.Tk()

img = ImageTk.PhotoImage(Image.open(path))
panel = tk.Label(root, image=img)
panel.pack(side="bottom", fill="both", expand="yes")

def callback(e):
    img2 = ImageTk.PhotoImage(Image.open(path2))
    panel.configure(image=img2)
    panel.image = img2

root.bind("<Return>", callback)
root.mainloop()

原始代码有效,因为图像存储在全局变量img中。

【讨论】:

@figs 似乎是有道理的。我不记得特别需要修改这种用法,但这也是四年多以前的事了。你能测试它来验证吗? 是的,这可能就是问题所在。使用略有不同的代码进行测试,但问题相同。 看来@Axl 删除了提到Alex Martelli 提出这个的信用。 @skeggse 我删除了它,因为我认为根本没有必要。当有人在寻找相同问题的解决方案时,他/她不在乎谁建议或不建议什么,他/她只想要一个具体的答案。 是的,但是考虑到我并不是真正想出解决方案的人,让我看起来好像已经想出了一个解决方案对我来说是不公平的。【参考方案2】:

另一种选择。

使用面向对象的编程和交互式界面来更新图像。

from Tkinter import *
import tkFileDialog
from tkFileDialog import askdirectory
from PIL import  Image

class GUI(Frame):

    def __init__(self, master=None):
        Frame.__init__(self, master)
        w,h = 650, 650
        master.minsize(width=w, height=h)
        master.maxsize(width=w, height=h)
        self.pack()

        self.file = Button(self, text='Browse', command=self.choose)
        self.choose = Label(self, text="Choose file").pack()
        self.image = PhotoImage(file='cualitativa.gif')
        self.label = Label(image=self.image)


        self.file.pack()
        self.label.pack()

    def choose(self):
        ifile = tkFileDialog.askopenfile(parent=self,mode='rb',title='Choose a file')
        path = ifile.name
        self.image2 = PhotoImage(file=path)
        self.label.configure(image=self.image2)
        self.label.image=self.image2


root = Tk()
app = GUI(master=root)
app.mainloop()
root.destroy()

将“cualitativa.jpg”替换为您要使用的默认图像。

【讨论】:

【参考方案3】:

另一个可能有帮助的解决方案。

就我而言,我有两个 tk.Tk() 窗口。当使用ImageTk.PhotoImage() 时,对象默认将其tk 窗口设置为第一个创建的窗口。一个简单的解决方法是传递你想要的 tk 窗口 ImageTk.PhotoImage(img, master=your_window)

import tkinter as tk 
from PIL import ImageTk, Image
if __name__ == '__main__':
     main_window = tk.Tk()
     second_window = tk.Tk()
     
     main_canvas = Canvas(second_window)
     main_canvas.pack()
     
     filename = 'test.png'

     img = Image.open(filename)
     img = img.resize((300, 100), Image.ANTIALIAS)
     logo = ImageTk.PhotoImage(img, master=second_window)
     logo_label = Label(master=main_canvas, image=logo)
     logo_label.image = logo
     logo_label.pack()

     main_window.mainloop()

【讨论】:

以上是关于如何更新 Tkinter 标签小部件的图像?的主要内容,如果未能解决你的问题,请参考以下文章

在图像框架上叠加tkinter小部件

如何在 tkinter 中找出当前小部件的大小?

如何同时移动两个 tkinter 小部件但异步?

如何查看 Tkinter 中是不是存在小部件?

如何在tkinter中找出当前的小部件大小?

使用继承正确扩展 tkinter 小部件