Newbie Tkinter Question

Discussion in 'Python' started by Pseud O'Nym, Apr 13, 2005.

  1. Pseud O'Nym

    Pseud O'Nym Guest

    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?
     
    Pseud O'Nym, Apr 13, 2005
    #1
    1. Advertising

  2. Pseud O'Nym

    Paul Rubin Guest

    "Pseud O'Nym" <> writes:
    > 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?
     
    Paul Rubin, Apr 13, 2005
    #2
    1. Advertising

  3. Pseud O'Nym

    Peter Otten Guest

    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
     
    Peter Otten, Apr 14, 2005
    #3
  4. 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
     
    Hans Georg Krauthaeuser, Apr 14, 2005
    #4
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jeff Epler
    Replies:
    0
    Views:
    511
    Jeff Epler
    Aug 20, 2004
  2. Jeff Epler
    Replies:
    0
    Views:
    459
    Jeff Epler
    Aug 23, 2004
  3. Pierre Dagenais
    Replies:
    0
    Views:
    321
    Pierre Dagenais
    Aug 3, 2008
  4. Hidekazu IWAKI
    Replies:
    1
    Views:
    384
    Peter Otten
    Dec 14, 2009
  5. Hidekazu IWAKI
    Replies:
    0
    Views:
    529
    Hidekazu IWAKI
    Dec 15, 2009
Loading...

Share This Page