问题
I have created a python class which inherits Tk from tkinter library. I want to add a label with an image to it but it only works when I create a Photoimage as variable to 'self'.
This code works:
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()
And this code doesn't work:
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()
Can anyone explain why the first code does work and the second code doesn't?
回答1:
PhotoImage
reads the image data from file and stores it in memory as a pixel buffer. The reference of this buffer has to be persistent as long as the application runs (or at least, as long the Label widget showing the image exists).
If you put the result of PhotoImage in a local variable (e.g. img
, as in the second code), the garbage collector is likely to destroy the data referenced by this local variable. On the other hand, if you store the reference of your pixel buffer in an attribute (e.g. self.img
, as in the first code) the garbage collector will not destroy your data as long as self
exists, which means as long as the application runs...
If your GUI uses many images, a usual practice is to create an attribute self.images
that puts all required images either in a tuple or a dictionary (whether you prefer indexing them by numbers or by strings), that ensures that all images will be kept in memory.
来源:https://stackoverflow.com/questions/49797743/why-doesnt-a-local-name-with-a-photoimage-object-work-for-a-tkinter-label-imag