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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 12:07:24