Newbie Tkinter Question

P

Pseud O'Nym

Hi,

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)

Can anyone enlighten me?
 
P

Paul Rubin

Pseud O'Nym said:
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)

Can anyone enlighten me?

You do have this inside a frame whose main loop is running, I hope?
 
P

Peter Otten

Pseud said:
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
 
H

Hans Georg Krauthaeuser

Peter said:
Pseud O'Nym wrote:




self.image = image1




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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top