Tkinter类在函数内实例化时图片无法加载的问题排查
问题原因与解决方案
问题原因
函数open_GUI()内部创建的test = GUI()是局部变量,函数执行完毕后,Python的垃圾回收机制会销毁这个局部变量,连带销毁GUI实例及其内部的self.img(ImageTk.PhotoImage对象)。而Tkinter要求必须保持对PhotoImage对象的引用,才能让图片在窗口中正常显示,因此函数内实例化的窗口无法加载图片。
解决方案
只要让GUI实例或PhotoImage对象保持持久引用即可,以下是三种常用方法:
方法1:将实例保存为全局变量
修改open_GUI()函数,把GUI实例赋值给全局变量,避免被垃圾回收:
def open_GUI(): global gui_instance # 声明全局变量 gui_instance = GUI()
方法2:将实例绑定到根窗口属性
把GUI实例挂载到root窗口的属性上,利用root窗口的持久存在性保留引用:
def open_GUI(): root.gui_instance = GUI()
方法3:给Label额外绑定图片引用
在GUI类的__init__方法中,给Label对象添加对图片的引用,确保图片不会被提前回收:
class GUI: def __init__(self): self.toplevel = tk.Toplevel() self.img = ImageTk.PhotoImage(Image.open(IMAGE_PATH)) self.img_label = tk.Label(self.toplevel,image=self.img) self.img_label.image = self.img # 给Label绑定图片引用 self.img_label.place(x=0,y=0)
这种方法即使GUI实例被局部变量销毁,只要Toplevel窗口还存在,Label就会保留对图片的引用,图片就能正常显示。
修改后的完整代码示例
import tkinter as tk from PIL import Image,ImageTk IMAGE_PATH = "your_image_path_here" # 替换为你的图片路径 #GUI CLASS class GUI: def __init__(self): self.toplevel = tk.Toplevel() self.img = ImageTk.PhotoImage(Image.open(IMAGE_PATH)) self.img_label = tk.Label(self.toplevel,image=self.img) self.img_label.image = self.img # 添加图片引用绑定 self.img_label.place(x=0,y=0) #open the gui with a FUNCTION --> image now opens def open_GUI(): root.gui_instance = GUI() # 绑定到root属性 #root window root = tk.Tk() tk.Label(root,text="This is the root").pack() #tests test = GUI() open_GUI() root.mainloop()
内容的提问来源于stack exchange,提问作者Hunter Davies
相关产品推荐
相关产品推荐

