我在 tkinter 的列表框小部件中插入多个图像时遇到问题。当我插入新图像时,前一个图像消失了。我该怎么办?这是我遇到问题的代码:
img = PhotoImage(file = Client.dir + "emo1.gif")
self.listBox.insert(END, sender)
self.listBox.image_create(END, image=img)
self.listBox.insert(END, "n")
self.listBox.yview(END)
正如文档所述:(以及@BryanOakley的评论)
然后,图像对象可以在某些小部件(例如标签、按钮、菜单)支持
image
选项的任何地方使用。在这些情况下,Tk 不会保留对图像的引用。当删除对图像对象的最后一个 Python 引用时,图像数据也会被删除,Tk 将在使用图像的任何位置显示一个空框。
尽管@BryanOakley的建议绝对是最简单的解决方案,但它可以防止未使用的图像被垃圾回收,这可能是不需要的。
注意:我建议的解决方案是假设self.listBox
是一个Text
小部件,因为Listbox
小部件没有image_create
方法。 如果您使用的是不同类型的小部件,那么您仍然可以创建一个类似的类来处理引用使用的图像。
您可以创建一个Text
子类,通过覆盖相关方法(image_create
和delete
是最重要的方法)来保留对插入的图像的引用:
from tkinter import Text #, PhotoImage, Tk
class Text_autoReferenceImage(Text):
def __init__(self,*varg,**kw):
self.images = {}
Text.__init__(self,*varg,**kw)
def image_create(self,index,**options):
img = options.get("image",None)
name = Text.image_create(self,index,**options)
if img is not None:
self.images[name] = img #this may remove previous reference with same name but different image
return name
def delete(self,*varg,**kw):
Text.delete(self,*varg,**kw)
self.clean_up_images()
def clean_up_images(self):
"""deletes reference to all images that are no longer present in Text widget (called by .delete())"""
images_still_in_use = self.image_names()
for name in set(self.images.keys()): #need to put .keys() into a set in python3 or it complains about dictionary changing size during iteration
if name not in images_still_in_use:
del self.images[name]
def destroy(self):
self.images.clear() #remove all references to own images
return Text.destroy(self)
然后,如果self.listBox
是此类的实例而不是Text
它将为您处理图像引用。