点击运行按钮后Tkinter画布无法显示本地图片
Tkinter点击Run按钮画布不显示图片的修复方案
问题根因
无报错但图片完全不渲染的核心原因是:Tkinter的PhotoImage对象会被Python垃圾回收机制自动销毁。
你在run_it()函数内部生成的图片对象属于函数局部作用域,run_it()执行完成后,这个局部引用会立刻被释放。如果没有其他强引用持有这个ImageTk.PhotoImage实例,Python垃圾回收器会直接回收对应的图片内存——哪怕你已经把它传给了canvas.create_image(),画布拿到的也只是一个已经失效的空引用,最终自然显示不出图片。
这个问题和你当前使用的第一代Surface Pro、Ubuntu 20.04、Python 3.8.5的运行环境完全无关,不需要做系统层面的兼容性排查。
修复方式
只需要给生成的PhotoImage对象绑定一个和主窗口生命周期一致的强引用,阻止它被垃圾回收即可。最简便的实现是把图片对象直接挂载为画布实例的自定义属性。
可正常运行的调整后代码
import tkinter as tk from PIL import ImageTk, Image ######## event handlers ########## # Event handler for the 'Close' button def close_it(): exit(0) # Event handler for the 'Run' button def run_it(): img = Image.open("google.png") # img = img.resize((250, 250), Image.ANTIALIAS) tk_img = ImageTk.PhotoImage(img) # 关键修复:将图片对象绑定到画布属性,维持长生命周期引用 canvas.image = tk_img canvas.create_image(1, 1, image = tk_img, anchor = tk.NW) ######### main ########### # Create the root window window = tk.Tk() window.title("Simple HTTP Image Browser") # Two frames: display_frame = tk.Frame(master = window) run_close_frame = tk.Frame(master = window) display_frame.pack(side = tk.TOP, fill = tk.BOTH) run_close_frame.pack(side = tk.TOP) # Canvas for image display canvas = tk.Canvas(master = display_frame, width = 600, height = 600) canvas.pack(side = tk.LEFT, fill = tk.Y) # Two buttons run_button = tk.Button(text = "Run", master = run_close_frame, command = run_it) close_button = tk.Button(text = "Close", master = run_close_frame, command = close_it) run_button.pack(side = tk.LEFT) close_button.pack(side = tk.LEFT) window.mainloop()
注意事项
- 不要直接把函数内的局部图片变量传给
canvas.create_image()就结束流程,函数执行完毕后局部引用会自动消失 - 除了把图片绑定到画布属性上,也可以维护一个全局的已加载图片列表,每次生成新的
PhotoImage实例就追加到列表中,只要列表和主程序生命周期一致,就不会触发垃圾回收 - 额外确认脚本运行的当前工作目录下确实存在
google.png文件,避免因为路径不对触发的静默加载失败
内容的提问来源于stack exchange,提问作者Rene Reitsma
相关产品推荐
相关产品推荐

