Tkinter按钮置于类方法中图片不显示的问题求助
问题描述
我编写了如下Python Tkinter代码:
初始代码
import tkinter as tk from tkinter import ttk class Window(tk.Tk): def __init__(self) -> None: super().__init__() self.mainloop()
我想要给窗口添加带图片的按钮,将按钮代码写在__init__方法中时,按钮可正常显示图片:
正常显示图片的代码
import tkinter as tk from tkinter import ttk class Window(tk.Tk): def __init__(self) -> None: super().__init__() img = tk.PhotoImage(file="close.png") button = ttk.Button(self, text="Click me!", image=img, compound="right") button.config(image=img) button.pack() self.mainloop()
(按钮可正常显示图片)
但当我将按钮代码移至类的closeButton方法中时,按钮无法显示图片:
无法显示图片的代码
import tkinter as tk from tkinter import ttk class Window(tk.Tk): def __init__(self) -> None: super().__init__() self.closeButton() self.mainloop() def closeButton(self): img = tk.PhotoImage(file="close.png") button = ttk.Button(self, text="Click me!", image=img, compound="right") button.config(image=img) button.pack()
(按钮无法正常显示图片)
我尝试过使用PIL加载图片,也试过单独为按钮创建类,但都没有解决问题。请问这是什么原因?该如何解决?
解答
原因
这是Python垃圾回收机制导致的问题:
- 在
__init__方法中,img是局部变量,但因为mainloop()在同一个方法内持续运行,变量不会被回收,所以图片能正常显示。 - 当代码移到
closeButton方法后,方法执行完毕时,局部变量img会被Python的垃圾回收器销毁。而Tkinter的PhotoImage没有在内部保留对自身的强引用,一旦Python层面的引用消失,图片资源就会被释放,按钮自然显示不出图片。
解决方法
只需要给img保留一个不会被轻易回收的引用即可,有两种常用方式:
方式1:将图片绑定为实例属性
把img赋值给self的属性,让实例持有它的引用:
import tkinter as tk from tkinter import ttk class Window(tk.Tk): def __init__(self) -> None: super().__init__() self.closeButton() self.mainloop() def closeButton(self): self.img = tk.PhotoImage(file="close.png") # 绑定为实例属性 button = ttk.Button(self, text="Click me!", image=self.img, compound="right") button.pack()
方式2:将图片绑定到按钮对象上
把img作为按钮的一个属性,让按钮持有引用:
import tkinter as tk from tkinter import ttk class Window(tk.Tk): def __init__(self) -> None: super().__init__() self.closeButton() self.mainloop() def closeButton(self): img = tk.PhotoImage(file="close.png") button = ttk.Button(self, text="Click me!", image=img, compound="right") button.img = img # 绑定到按钮对象 button.pack()
这两种方式都能避免img被垃圾回收,图片就能正常显示在按钮上了。
内容的提问来源于stack exchange,提问作者wojtas558
相关产品推荐
相关产品推荐

