在tkinter中,这是避免不必要的垃圾收集的好方法吗?

2024-10-17 08:30:45 发布

您现在位置:Python中文网/ 问答频道 /正文

在Tkinter中,我们有时必须创建对 转换后的图像(例如),以便在超出范围时不会被销毁。你知道吗

一种常见的方法是将变量添加到其小部件实例中。例如:

    bard = Image.open("bardejov.jpg")
    bardejov = ImageTk.PhotoImage(bard)
    label1 = Label(self, image=bardejov)
    label1.image = bardejov #<<<<<<<<<<<<<<<<<<<<<
    label1.place(x=20, y=20)

这是Zetcode的Jan Bodnar发布的一个示例的一部分,我标记了这个示例。bardejov是函数中的一个局部变量,如果注释掉标记的行,就不会得到图像,因为当函数返回时图像会被破坏,标签只会看到“none”。你知道吗

我是Tkinter的新手,这让我很担心,在系统代码中添加新属性,有人建议:

class S():
    # To make an object 'accessible', and thus save 
    # it from garbage collection.
    fred = []
    @classmethod
    def save(cls, x):
        cls.fred.append(x)

这在简的例子中确实奏效了:

bard = Image.open("xxxx.jpg")
bardejov = ImageTk.PhotoImage(bard)
label1 = Label(self, image=bardejov)
#label1.image = bardejov
S.save(bardejov)

但是还好吗?有什么不良反应吗?你知道吗


Tags: 图像imageself示例tkintersaveopenlabel
1条回答
网友
1楼 · 发布于 2024-10-17 08:30:45

Question: good way of avoiding unwanted garbage collection?

这不是问题,不管好坏,你都必须去做。
你可以定义自己的PhotoImageLabel,而不是一遍又一遍地做。你知道吗

例如:

import tkinter as tk
from PIL import Image, ImageTk


class PhotoImageLabel(tk.Label):
    def __init__(self, parent, **kwargs):
        image = Image.open(kwargs['image'])
        self._image = ImageTk.PhotoImage(image)

        kwargs['image'] = self._image
        super().__init__(parent, **kwargs)

Usage:

class App(tk.Tk):
    def __init__(self):
        super().__init__()

        self.photo_label = PhotoImageLabel(self, image="xxxx.jpg")
        self.photo_label.grid()


if __name__ == '__main__':
    App().mainloop()

Comment: One day I guess the widget itself will fix the problem

这不太可能,因为ImageTk.PhotoImage不是tkinter的一部分。 通过将图像对象绑定到小部件,可以扩展PhotoImage,使其行为类似于tkinter对象:

例如:

class PhotoImage(ImageTk.PhotoImage):
    def __init__(self, parent, **kwargs):
        image = kwargs['image']

        # PIL.Image => .PhotoImage
        super().__init__(image)

        # Update <widget>.children with [self.__photo.name] = self
        self._ref = parent.children
        self._ref[self.__photo.name] = self

    def destroy(self):
        # This gets called on `.destroy()` the parent
        # Delete the reference in parent.children
        del self._ref[self.__photo.name]

Usage:

class PhotoImageLabel(tk.Label):
    def __init__(self, parent, **kwargs):
        image = Image.open(kwargs['image'])

        # Get a PhotoImage object which is bound to 'self'
        kwargs['image'] = PhotoImage(self, image=image)

        super().__init__(parent, **kwargs)

相关问题 更多 >