As mentioned in this very answer and this more popular question & answer and also in effbot.page
When you add a PhotoImage or other Image object to a Tkinter widget,
you must keep your own reference to the image object. If you don’t,
the image won’t always show up.
The problem is that the Tkinter/Tk interface doesn’t handle references
to Image objects properly; the Tk widget will hold a reference to the
internal object, but Tkinter does not. When Python’s garbage collector
discards the Tkinter object, Tkinter tells Tk to release the image.
But since the image is in use by a widget, Tk doesn’t destroy it. Not
completely. It just blanks the image, making it completely
transparent…
The solution is to make sure to keep a reference to the Tkinter
object,
For example the image
in below code
, if at all as it isn't declared in global scope:
import tkinter as tk
root = tk.Tk()
def show_image():
img_label = tk.Label(root)
image = tk.PhotoImage(file="test.png")
img_label['image'] = image
img_label.pack()
show_image()
root.mainloop()

whereas in the example below img_label.image
is declared globally, as an attribute attached to our very img_label
in this example, and
:
import tkinter as tk
root = tk.Tk()
def show_image():
img_label = tk.Label(root)
img_label.image = tk.PhotoImage(file="test.png")
img_label['image'] = img_label.image
img_label.pack()
show_image()
root.mainloop()

It is though still strange as img_label
isn't globally declared either. A less confusing way would be adding global image
as the first line to the show_image
.