Tkinter中图片在Window1显示但Window2不显示的原因?(Python3)
Tkinter中顶级窗口图片不显示的原因分析
以下Python3代码中,使用Tkinter创建主窗口Window1和顶级窗口Window2,二者均尝试通过ttk.Label显示本地GIF图片。实际运行时图片在Window1正常显示,在Window2却无法显示;但将图片作为参数传入picture()函数时,Window2可正常显示图片,请问该现象的原因是什么?
问题代码
import tkinter as tk from tkinter import ttk def picture(): window2 = tk.Toplevel() window2.title("Window2") window2.geometry("300x300") window2.configure(background='grey') f = "C:\\Users\\Bob\\Documents\\Python\\bb.gif" img = tk.PhotoImage(file=f) panel = ttk.Label(window2, width=100, background="green", image=img) panel.grid(column=1, row=1, sticky=(tk.W,tk.E)) # Start the GUI window = tk.Tk() window.title("Window1") window.geometry("300x300") window.configure(background='grey') f = "C:\\Users\\Bob\\Documents\\Python\\bb.gif" img = tk.PhotoImage(file=f) panel = ttk.Label(window, width=100, background="green", image=img) panel.grid(column=1, row=1, sticky=(tk.W,tk.E)) picture() window.mainloop()
原因解析
这其实是Tkinter里一个非常常见的垃圾回收陷阱,我给你拆解清楚:
- 主窗口的
img是全局作用域变量:只要主程序在运行,这个变量就会一直存在,Tkinter的PhotoImage对象靠着这个Python层面的引用,不会被垃圾回收机制销毁,所以Window1的图片能正常显示。 picture()函数里的img是局部变量:函数执行完毕后,Python会自动回收这个局部变量的引用。而Tkinter的PhotoImage必须依赖Python端的引用才能和组件保持关联,一旦局部img被回收,图片对象就会被销毁,Window2的Label自然就没东西可显示了。
至于把图片作为参数传入函数就能解决,是因为此时img的引用来自外部(比如全局作用域),函数执行完后这个引用依然存在,PhotoImage对象不会被回收,所以Window2的图片就能正常显示。
给你个快速修复小技巧:不用改参数传递,只要在函数里给Label绑定图片引用就行,比如加一行panel.image = img。这样Label组件会持有图片的引用,只要Label没被销毁,图片就不会被回收。
内容的提问来源于stack exchange,提问作者lyndalebob
相关产品推荐
相关产品推荐

