Newbie question on Tkinter
Eric Brunel
eric.brunel at pragmadev.com
Thu Jul 4 04:04:23 EDT 2002
Michele Simionato wrote:
> I have found a confusing (to me) behavior of Tkinter in displaying GIF
> images.
> Consider the following four programs (assuming you have a GIF image
> called 'picture.gif' in the current directory):
>
> #Program 1: works
> import Tkinter
> root=Tkinter.Tk()
> img=Tkinter.PhotoImage(file='picture.gif')
> lbl=Tkinter.Label(root,image=img)
> lbl.pack()
> Tkinter.mainloop()
>
> #Program 2: doesn't work
> import Tkinter
> root=Tkinter.Tk()
> lbl=Tkinter.Label(root,image=Tkinter.PhotoImage(file='picture.gif'))
> lbl.pack()
> Tkinter.mainloop()
>
> #Program 3: doesn't work
> import Tkinter
> def DisplayPicture(root,picture):
> img=Tkinter.PhotoImage(file='picture.gif')
> lbl=Tkinter.Label(root,image=img)
> lbl.pack()
> root=Tkinter.Tk()
> DisplayPicture(root,'picture.gif')
> Tkinter.mainloop()
>
> #Program 4: works
> import Tkinter
> def DisplayPicture(root,picture):
> global img
> img=Tkinter.PhotoImage(file='picture.gif')
> lbl=Tkinter.Label(root,image=img)
> lbl.pack()
> root=Tkinter.Tk()
> DisplayPicture(root,'picture.gif')
> Tkinter.mainloop()
>
> The second program should give the same output of the first one,
> however
> the first one works, the second one gives a transparent picture! Why
> ??
> The only difference is that there is no explicit name for the
> PhotoImage object.
> Moreover: program 3 has an explicit name for the PhotoImage, but the
> picture is still
> transparent ! Why ?? By trials, I discovered that it is possible to
> fix the problem
> at the price of making the PhotoImage name a global variable (see
> program 4).
You just encountered the weirdest "feature" of Tkinter: it doesn't keep
references on images, even if they are used. If you're unfamiliar with the
concept of references in Python, you may at first read the corresponding
chapter in the reference manual (
http://www.python.org/doc/current/ref/objects.html ). Anyway, here is the
explanation of the behaviour you've seen:
- your program #1 works because when you start Tkinter mainloop, there is
still an explicit reference to your image (the variable "img")
- your program #2 does not work because:
lbl=Tkinter.Label(root,image=Tkinter.PhotoImage(file='picture.gif'))
does *not* keep a reference on the created image. Therefore, just after
this statement, the created instance is deleted and can't be used
- your program #3 does not work because the only reference you created in
your DisplayPicture function (img) was local to the function, so it was
discarded at the function return. Since:
lbl=Tkinter.Label(root,image=img)
does *not* add a reference to the image, again, the picture was deleted at
the end of your DisplayPicture function
- your program #4 works because since the variable "img" is global, it
still exists when Tkinter's mainloop is called, so the image is still
referenced and can be used.
You may think it's a bug (and I'm personally not convinced that it isn't
one...), but it is not considered as a bug by Tkinter designers (see Python
FAQ, entry 4.69 at
http://www.python.org/cgi-bin/faqw.py?req=show&file=faq04.069.htp )
> How can I avoid that ?
To keep things simple, I'd try to create a sub-class of Tkinter.PhotoImage
that remembers its instances:
import Tkinter
class MyPhotoImage(Tkinter.PhotoImage):
instances = []
def __init__(self, *args, **options):
apply(Tkinter.PhotoImage.__init__, (self,) + args, options)
MyPhotoImage.instances.append(self)
Then try:
root=Tkinter.Tk()
lbl=Tkinter.Label(root,image=MyPhotoImage(file='picture.gif'))
lbl.pack()
Tkinter.mainloop()
and it should work the way you expect. But note that all images you'll
create with this class will be remembered, even unused ones. It may eat up
memory quite fast if you have lots of images (and/or big ones...).
The other solution is to explicitely keep a reference on every image you
use, taking care of deleting the reference when the image is not used
anymore.
> P.S. BTW, how to display jpeg images ?
I think PIL can do that, but I'm not sure. See
http://www.pythonware.com/products/pil/
HTH
--
- Eric Brunel <eric.brunel at pragmadev.com> -
PragmaDev : Real Time Software Development Tools - http://www.pragmadev.com
More information about the Python-list
mailing list