'Why does Tkinter image not show up if created in a function?
This code works:
import tkinter
root = tkinter.Tk()
canvas = tkinter.Canvas(root)
canvas.grid(row = 0, column = 0)
photo = tkinter.PhotoImage(file = './test.gif')
canvas.create_image(0, 0, image=photo)
root.mainloop()
It shows me the image.
Now, this code compiles but it doesn't show me the image, and I don't know why, because it's the same code, in a class:
import tkinter
class Test:
def __init__(self, master):
canvas = tkinter.Canvas(master)
canvas.grid(row = 0, column = 0)
photo = tkinter.PhotoImage(file = './test.gif')
canvas.create_image(0, 0, image=photo)
root = tkinter.Tk()
test = Test(root)
root.mainloop()
Solution 1:[1]
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)
Solution 2:[2]
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
Solution 3:[3]
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:
Solution 4:[4]
Just add global photo
as the first line inside the function.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | martineau |
Solution 2 | TIRTH SHAH |
Solution 3 | |
Solution 4 | Gabriel |