Why does Tkinter image not show up if created in a function?
The variable photo
is a local variable which gets garbage collected after the class is instantiated. Save a reference to the photo, for example:
self.photo = tkinter.PhotoImage(...)
If you do a Google search on "tkinter image doesn't display", the first result is this:
Why do my Tkinter images not appear? (The FAQ answer is currently not outdated)
from tkinter import *
from PIL import ImageTk, Image
root = Tk()
def open_img():
global img
path = r"C:\.....\\"
img = ImageTk.PhotoImage(Image.open(path))
panel = Label(root, image=img)
panel.pack(side="bottom", fill="both")
but1 = Button(root, text="click to get the image", command=open_img)
but1.pack()
root.mainloop()
Just add global to the img definition and it will work
The problem is Python automatically deletes the references to the variable by a process known as Garbage Collection. The solution is to save the reference or to create a new reference.
The following are the ways:
- Using
self
to increase the reference count and to save the reference.
import tkinter
class Test:
def __init__(self, master):
canvas = tkinter.Canvas(master)
canvas.grid(row = 0, column = 0)
self.photo = tkinter.PhotoImage(file = './test.gif') # Changes here
canvas.create_image(0, 0, image=self.photo) # Changes here
root = tkinter.Tk()
test = Test(root)
root.mainloop()
- Saving it to a list to increase the reference count and to save the reference.
import tkinter
l=[]
class Test:
def __init__(self, master):
canvas = tkinter.Canvas(master)
canvas.grid(row = 0, column = 0)
photo = tkinter.PhotoImage(file = './test.gif')
l.append(photo)
canvas.create_image(0, 0, image=photo)
root = tkinter.Tk()
test = Test(root)
root.mainloop()
While using method 2, you can either make a global list as i did or use list inside the class. Both would work.
Some useful links:
- About Garbage Collection 1
- About Garbage Collection 2 (More useful)