为什么带有 PhotoImage 对象的本地名称对于 tkinter 标签图像不起作用?

Why doesn't a local name with a PhotoImage object work, for a tkinter label image?

我创建了一个 python class,它从 tkinter 库继承了 Tk。 我想给它添加一个带有图像的标签,但只有当我创建一个照片图像作为 'self' 的变量时它才有效。

此代码有效:

class HMIDrawer(Tk):

    def __init__(self):
        super().__init__()

        self.frame = Frame(self)
        self.img = PhotoImage(file='resources/platoontomtom_empty.png')
        self.label = Label(self.frame, image=self.img, bg='white')
        self.label.pack()
        self.frame.pack()
        self.mainloop()

此代码无效:

class HMIDrawer(Tk):

    def __init__(self):
        super().__init__()

        self.frame = Frame(self)
        img = PhotoImage(file='resources/platoontomtom_empty.png')
        self.label = Label(self.frame, image=img, bg='white')
        self.label.pack()
        self.frame.pack()
        self.mainloop()

谁能解释为什么第一个代码有效而第二个代码无效?

PhotoImage 从文件中读取图像数据并将其作为像素缓冲区存储在内存中。只要应用程序运行(或至少,只要显示图像的标签小部件存在),此缓冲区的引用就必须持久。

如果将PhotoImage的结果放在一个局部变量中(例如img,如第二段代码),垃圾收集器很可能会破坏这个局部变量引用的数据。另一方面,如果您将像素缓冲区的引用存储在属性中(例如 self.img,如第一个代码中所示),只要 self 存在,垃圾收集器就不会破坏您的数据,这意味着只要应用程序运行...

如果您的 GUI 使用许多图像,通常的做法是创建一个属性 self.images,将所有需要的图像放入元组或字典中(无论您喜欢按数字还是按字符串索引它们),确保所有图像都保存在内存中。