Newbie Tkinter Question

Hans Georg Krauthaeuser hgk at et.uni-magdeburg.de
Thu Apr 14 02:33:42 EDT 2005


Peter Otten schrieb:
> Pseud O'Nym wrote:
> 
> 
>>the following fragment doesn't cause any errors and results in buttons the
>>correct size for the images, but the buttons don't work, and the images
>>aren't displayed. If I add a text property, and remove the images, they
>>work fine, so the rest of my code's OK. I've searched this group and
>>Python.org to no avail.
>>
>>class App:
>>  def __init__(self, master):
>>    frame = Frame(master)
>>    frame.pack(side=LEFT, fill=Y)
>>    image1 = PhotoImage(file='button_a.gif')
>>    self.button = Button(frame, image=image1)
>>    self.button.pack(side=TOP)
> 
> 
>       self.image = image1
> 
> 
>>Can anyone enlighten me?
> 
> 
> For reasons that are beyond me widgets do not increase the reference count
> of a PhotoImage. Therefore you have to put a reference to the image
> elsewhere, e. g. into the App instance, to prevent it from being
> garbage-collected when the image1 variable goes out of scope.
> 
> Peter
> 
Because I stumbled across the same 'feature' just recently, I think it's
good to give a reference...

>From http://tkinter.unpythonic.net/wiki/Images

"Something that seems to bite every new Tkinter programmer at least
once: you've loaded a PhotoImage, applied it to a Button, Label, or
other widget, and nothing shows up - because you referenced the image
only via a local variable, so it went out of scope and got deleted
before the widget ever appeared. The usual solution is to store a
reference to the image as an attribute of the widget that is to display it.

You might just call this a bug in Tkinter, but the reality isn't quite
that simple... Tk images are not first-class objects: when you apply one
to a widget, you do not in any sense "pass a reference to" the image.
Instead, you just pass a name, which Tk looks up in an internal table of
defined images (from which images can only be deleted manually). From
Tkinter, passing a PhotoImage as a parameter actually only sends the
str() of the image object to the Tcl side: this is just a string, the
randomly-generated name assigned when the object was created. "No
reference to the image itself" means "no reference counting" means "no
way for the Python side to be notified when the image is truly no longer
used". If Tkinter didn't delete images when no Python reference to them
existed, they would be unavoidable memory leaks.
..."

Hans Georg



More information about the Python-list mailing list