Tkinter Canvas Does Not Display

SooDesuNe picture SooDesuNe · Feb 8, 2010 · Viewed 8.4k times · Source

I'm attempting to learn some Python and Tkinter. The sample code below is intended to put two windows on the screen, a few buttons, and a Canvas with an image in it and some lines drawn on it.

The windows and buttons appear just fine, however I'm not seeing either the canvas image or canvas lines. I'd appreciate some help to figure out what's need to make my canvas display.

from Tkinter import *
import Image, ImageTk

class App:

    def __init__(self, master):

    def scrollWheelClicked(event):
        print "Wheel wheeled"

    frame = Frame(master)
    frame.pack()
    self.button = Button(frame, text = "QUIT", fg="red", command=frame.quit)
    self.button.pack(side=LEFT)

    self.hi_there = Button(frame, text="Hello", command=self.say_hi)
    self.hi_there.pack(side=LEFT)

    top = Toplevel()
    canvas = Canvas(master=top, width=600, height=600)

    image = Image.open("c:\lena.jpg")
    photo = ImageTk.PhotoImage(image)
    item = canvas.create_image(0, 0, image=photo)

    canvas.create_line(0, 0, 200, 100)
    canvas.create_line(0, 100, 200, 0, fill="red", dash=(4, 4))
    canvas.create_rectangle(50, 25, 150, 75, fill="blue")

    canvas.pack

    testBtn = Button(top, text = "test button")
    testBtn.pack()

def say_hi(self):
    print "hi there everyone!"

root = Tk()
app = App(root)
root.mainloop()

Answer

Yauhen picture Yauhen · Oct 27, 2010

I solved this problem:

self.photo = ImageTk.PhotoImage(image)
self.item = canvas.create_image(0, 0, image=self.photo)

A reference to the ImageTk instance must be stored somewhere, or when your App.__init__() method returns, it will be garbage collected, and the canvas will not be able to display it. (Tkinter does not keep a reference to the image.)

One way to keep a reference to it is by storing it in "self.photo", or a variable named 'photo', or, like most programmers do for constant variables (variables that don't change, like 'TEN = 10'), 'PHOTO = PhotoImage(...)' Of why... I have no idea. Importing the module 'gc' (Python 3's garbage collection module, built in) and running gc.disable() doesn't work. (If you want to try it: https://docs.python.org/3/library/gc.html)