多窗口图片显示故障求助:基于Tkinter的弹窗程序问题排查
解决Tkinter多窗口无法显示图片的问题
问题出在ImageTk.PhotoImage的生命周期上——当你直接在Label参数里创建这个对象时,没有保留它的引用,Python的垃圾回收机制会把它销毁,导致窗口里显示不出图片。
下面是修复后的代码:
from tkinter import Tk, mainloop, Label from random import randint from PIL import ImageTk, Image def Spawn(self): self.win = Tk() # 随机设置窗口大小和位置 self.win.geometry(f"{randint(10,1000)}x{randint(10,1000)}+{randint(-20,800)}+{randint(-20,500)}") # 加载图片并保存为实例属性,避免被垃圾回收 self.img = ImageTk.PhotoImage(Image.open(r"bean.jpg")) # 先创建Label再调用pack(),避免把None赋值给self.win.label self.win.label = Label(self.win, image=self.img) self.win.label.pack() self.win.protocol("WM_DELETE_WINDOW", self.MULTIPLY) class ULTRASUS(): def __init__(self): Spawn(self) def MULTIPLY(self): self.win.destroy() Spawn(self) for _ in range(25): ULTRASUS() mainloop()
关键修改说明:
- 保留图片引用:把
ImageTk.PhotoImage对象赋值给self.img,让实例持有这个引用,防止被垃圾回收。这是Tkinter显示图片的常见坑。 - 拆分Label创建与pack():
pack()方法返回None,之前的代码里self.win.label实际是None,拆分后写法更规范,也方便后续对Label进行操作。 - 格式化字符串优化:用f-string替代字符串拼接,代码更简洁易读。
如果想进一步优化性能,可以把图片加载放到类的__init__方法里,只加载一次图片复用,减少重复IO开销:
from tkinter import Tk, mainloop, Label from random import randint from PIL import ImageTk, Image def Spawn(self): self.win = Tk() self.win.geometry(f"{randint(10,1000)}x{randint(10,1000)}+{randint(-20,800)}+{randint(-20,500)}") # 复用已加载的图片 self.win.label = Label(self.win, image=self.img) self.win.label.pack() self.win.protocol("WM_DELETE_WINDOW", self.MULTIPLY) class ULTRASUS(): def __init__(self): # 只加载一次图片 self.img = ImageTk.PhotoImage(Image.open(r"bean.jpg")) Spawn(self) def MULTIPLY(self): self.win.destroy() Spawn(self) for _ in range(25): ULTRASUS() mainloop()
内容的提问来源于stack exchange,提问作者Haise
相关产品推荐
相关产品推荐

