views:

130

answers:

1

I'm noticing a pretty strange bug with tkinter, and I am wondering if it's because there's something in how the python interacts with the tcl, at least in Win32.

Here I have a super simple program that displays a gif image. It works perfectly.

from Tkinter import *

canvas = Canvas(width=300, height=300, bg='white')   
canvas.pack()

photo=PhotoImage(file=sys.argv[1])
canvas.create_image(0, 0, image=photo, anchor=NW)  # embed a photo
print canvas
print photo

mainloop( )

Now, I change the program slightly to edit the canvas object from within a function. This time, I just get a blank canvas.

# demo all basic canvas interfaces
from Tkinter import *

canvas = Canvas(width=300, height=300, bg='white')

canvas.pack()

def set_canvas(cv):
    photo=PhotoImage(file=sys.argv[1])
    cv.create_image(0, 0, image=photo, anchor=NW)  # embed a photo
    print cv
    print photo

set_canvas(canvas)
mainloop( )

The only difference between the two is that in one the canvas object is passed to a function instead of being used directly. Both print statements return identical results. I am wondering if there is perhaps some breakdown in the object model at the tcl/python layer.

Any thoughts, folks?

Thanks, /YGA

+4  A: 

Do that as a quick solution, and I'll try to explain:

def set_canvas(cv):
    global photo # here!
    photo=PhotoImage(file=sys.argv[1])
    cv.create_image(0, 0, image=photo, anchor=NW)  # embed a photo
    print cv
    print photo

A PhotoImage needs to have at least one reference from any Python object, otherwise it's garbage collected. In my solution, I suggest to make photo be a module-level name, so when the function ends, there will still be a reference to the PhotoImage object. You might prefer to create a class and make set_canvas into a method, and store the PhotoImage object as an instance variable.

ΤΖΩΤΖΙΟΥ