KirkDCO KirkDCO - 8 months ago 81
Python Question

Tkinter create_image

I've been working to get a simple Tkinter canvas to display an image using create_image. I've read many threads that say that you need to create a reference to the object outside any function or class, otherwise the image object will be garbage collected. Unfortunately, I still cannot get this to work. Below is my code as it stands. Ignore all the colors - I use them to illustrate where the frames and canvas live on the window.


import Tkinter as tk
from PIL import Image
from PIL import ImageTk

imageList = []
image ='len_std.jpg')

#event handlers
def hit_sel_click():
imageList = []
test_image = ImageTk.PhotoImage(image)

#start root
root = tk.Tk()
root.resizable(width=False, height=False)

#target/control variables
hit_sel = tk.StringVar() #holds radio button with activity level

#build GUI
frm_hits = tk.Frame(root, height=800, width=200, bg='#FF0000')
frm_hits.grid(rowspan=3, sticky=tk.W+tk.N+tk.S+tk.E)

tk.Label(frm_hits, text='Activity:').grid()
tk.Radiobutton(frm_hits, text='Low', variable=hit_sel, value='Low',
tk.Radiobutton(frm_hits, text='Medium', variable=hit_sel, value='Medium',
tmp = tk.Radiobutton(frm_hits, text='High', variable=hit_sel,value='High',

frm_hit_list = tk.Frame(frm_hits, bg='#002288')

scrl_hits = tk.Scrollbar(frm_hit_list, orient=tk.VERTICAL)
scrl_hits.grid(row=0, column=1, sticky=tk.N+tk.S)

cnv_hits = tk.Canvas(frm_hit_list, bg='#888800',width=200, height=200,
cnv_hits.grid(row=0, column=0, sticky=tk.W+tk.N+tk.E+tk.S)




You are using test_image to draw the image of cnv_hits. That is right, but you forgot that test_image is local to hit_sel_click() method; which thing means it is not available to your main program.

To resolve this, you have 2 choices:

  • Either declare test_image as global inside hit_sel_click()
  • Or run test_image = ImageTk.PhotoImage(image) before you declare hit_sel_click().

Nota Bene:

  • For the first case, you will need to run root = tk.Tk() before hit_sel_click().

  • In case you choose the second option, you will need to run root = tk.Tk() before test_image = ImageTk.PhotoImage(image)

If you don't do this, your program will raise a RuntimeError exception.