Problem displaying images with TkInter

Eric Brunel eric.brunel at N0SP4M.com
Thu Mar 4 08:41:27 EST 2004


David wrote:
> Hi,
>         I'm new to python so I'm probably making a fairly simple mistake, but
> look at the example below. It simply displays a rectangle and an image.
> 
> -------------------------------------------------
> from Tkinter import *
> 
> root = Tk()
> 
> c = Canvas(root, width=1024, height = 1024)
> c.pack()
> 
> c.create_rectangle(10,10,50,50)
> mudPhoto = PhotoImage(file="/root/metropolis/mud.gif")
> c.create_image(50, 50, anchor=NW, image=mudPhoto)
> 
> root.mainloop()
> -----------------------------------------------
> 
> Now I try to modify it so that the image and rectangle only appear when I
> click the mouse on the canvas. I use the following code:
> 
> -----------------------------------------------
> from Tkinter import *
> 
> root = Tk()
> 
> def OnClick(event):
>     print "click!!!"
>     c.create_rectangle(10,10,50,50)
>     mudPhoto = PhotoImage(file="/root/metropolis/mud.gif")
>     c.create_image(50, 50, anchor=NW, image=mudPhoto)
> 
> c = Canvas(root, width=1024, height = 1024)
> c.pack()
> c.bind("<Button-1>",OnClick)
> root.mainloop()
> ----------------------------------------------
> 
> However when I click the mouse it prints 'click!!!' and draws the rectangle
> as expected. However it doesn't draw the image! Does anyone have any idea
> why this would be?

This used to be a FAQ, but I can't it anymore (anyone knows where it has gone?).

The problem lies in the fact that for some reason, the Canvas where you do the 
create_image does *not* keep a reference on the actual PhotoImage object. So 
this object disappears when your variable mudPhoto goes out of scope (i.e. at 
the end of your OnClick function), which causes its deletion at tk level. So 
when OnClick finishes, the canvas finds itself displaying an image that doesn't 
exist anymore.

The workaround is simple: always keep an explicit reference on all your 
PhotoImage and BitmapImage objects until you no more need them. For your 
particular case, this can be done via:

def OnClick(event):
     print "click!!!"
     c.create_rectangle(10,10,50,50)
     c.mudPhoto = PhotoImage(file="/root/metropolis/mud.gif")
     c.create_image(50, 50, anchor=NW, image=c.mudPhoto)

Turning mudPhoto into an attribute of the canvas ensures that it won't be 
deleted before the canvas is.

HTH
-- 
- Eric Brunel <eric dot brunel at pragmadev dot com> -
PragmaDev : Real Time Software Development Tools - http://www.pragmadev.com




More information about the Python-list mailing list