如果在函数中创建,为啥 Tkinter 图像不显示?

Posted

技术标签:

【中文标题】如果在函数中创建,为啥 Tkinter 图像不显示?【英文标题】:Why does Tkinter image not show up if created in a function?如果在函数中创建,为什么 Tkinter 图像不显示? 【发布时间】:2021-04-13 16:18:27 【问题描述】:

此代码有效:

import tkinter

root = tkinter.Tk()
canvas = tkinter.Canvas(root)
canvas.grid(row = 0, column = 0)
photo = tkinter.PhotoImage(file = './test.gif')
canvas.create_image(0, 0, image=photo)
root.mainloop()

它显示了图像。

现在,这段代码编译了,但它没有显示图像,我不知道为什么,因为它是相同的代码,在一个类中:

import tkinter

class Test:
    def __init__(self, master):
        canvas = tkinter.Canvas(master)
        canvas.grid(row = 0, column = 0)
        photo = tkinter.PhotoImage(file = './test.gif')
        canvas.create_image(0, 0, image=photo)

root = tkinter.Tk()
test = Test(root)
root.mainloop()

【问题讨论】:

effbot.org 已关闭。它的要点是图像是通过引用传递的。如果引用是对局部变量的引用,则引用的内存将被重用,并且引用变得陈旧。存储图像的变量应该与它出现的 Tk gui 对象在同一范围内(必须具有相同的生命周期)。 @maszoka: effbot.org 可能已关闭,但您仍然可以阅读链接 Why do my Tkinter images not appear? 感谢 Internet 档案库 wayback machine。 另请注意,在使用临时PhotoImages 的任何地方都可能出现相同的问题,例如在label = Label(image=ImageTk.PhotoImage(Image.fromarray(data))) 等调用序列中。 【参考方案1】:

变量photo 是一个局部变量,在类实例化后会被垃圾回收。保存对照片的引用,例如:

self.photo = tkinter.PhotoImage(...)

如果你对“tkinter image doesn't display”进行谷歌搜索,第一个结果是这样的:

Why do my Tkinter images not appear?(常见问题解答目前没有过时)

【讨论】:

lmao,很好的答案! 哇。他们认为这是 tkinter 中的错误吗?他们应该。 我发现了一张很旧的票,已经关闭,没有修复:bugs.python.org/issue632323 链接在atm无效,除了使用“global”还有其他方法吗? @TamasHegedus:我同意这是一个错误,但显然在(目前)近二十年后没有人费心去修复。已经数不清有多少次我看到一个关于它的问题仍然弹出。【参考方案2】:

只需将global photo 添加为函数内的第一行。

【讨论】:

然后你创建了第二个Test 实例,第一个实例丢失了它的图像。恭喜。 上课时绝对没有必要使用globalself. 负责所有这些。【参考方案3】:
from tkinter import *
from PIL import ImageTk, Image

root = Tk()

def open_img():
    global img
    path = r"C:\.....\\"
    img = ImageTk.PhotoImage(Image.open(path))
    panel = Label(root, image=img)
    panel.pack(side="bottom", fill="both")
but1 = Button(root, text="click to get the image", command=open_img)
but1.pack()
root.mainloop() 

只需将全局添加到 img 定义中即可使用

【讨论】:

这个答案对于只使用函数的程序来说很好,但是如果像 OP 的情况一样,你使用一个类,那么global 不是不是的方法去吧。

以上是关于如果在函数中创建,为啥 Tkinter 图像不显示?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 tkinter 中创建日期选择器?

在 Tkinter Python 中创建全局画布

在 scala 中创建的图像看起来不像预期的那样。不知道为啥

如何在 Tkinter 中创建垂直菜单栏?

如何在 Python Tkinter 中创建一个按钮以将整数变量增加 1 并显示该变量?

如何在 Tkinter 中创建带有标签的超链接?