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)
Tkinter Image not displaying in label or canvas
It is because you did not call any layout function on self.FrameBanner
:
...
self.FrameBanner.pack() # or whatever layout manager you want
self.frm_banner.grid(column=0, row=0)
...
Why is the image not showing in the tkinter using if conditions?
First of all, terrible names.
Both your function and your PhotoImage
are named img
. Rename the function to def add_img()
.
Second, looking at your code I have no idea what all the wrapper frames are for, why not name them according to what they are planned to hold? Same applies to all the widgets. Wouldn't calc_btn
be a better name than btn
? img_btn
instead of btn2
? Why do you need to read more than the name to know what something is?
Third, you have ent8 twice in your code. Once as Label and again as a StringVar.
Tkinter constantly refreshes your window so you need to save the image you are using.
Personally I would have done all of this in a class.
For right now, with your current code, just addloaded_img = ImageTk.PhotoImage(Image.open("Amritsar.jpg"))
before your functions and instead of using the variables you are using to open the image, just use Label(wrapper3, image=loaded_img)
As in:
win = Toplevel()
wrapper=Frame(win, bd=4, relief=RIDGE, bg="crimson")
wrapper.place(x=0, y=80, width=465, height=625)
wrapper3=Frame(win, bd=4, relief=RIDGE, bg="crimson")
wrapper3.place(x=950, y=80, width=465, height=625)
wrapper3_title=Label(wrapper3, text="Selected Data", bg="crimson", fg="white", font=("times new roman",30,"bold"))
wrapper3_title.grid(row=0,column=0,padx=20, pady=10)
wrapper2=Frame(win, bd=4, relief=RIDGE, bg="crimson")
wrapper2.place(x=465, y=80, width=485, height=625)
ent8=StringVar()
loaded_img = ImageTk.PhotoImage(Image.open("Amritsar.jpg"))
Edit
Here is the entire code:
from tkinter import *
from tkinter import ttk
from PIL import ImageTk ,Image
win=Toplevel()
wrapper=Frame(win, bd=4, relief=RIDGE, bg="crimson")
wrapper.place(x=0, y=80, width=465, height=625)
wrapper3=Frame(win, bd=4, relief=RIDGE, bg="crimson")
wrapper3.place(x=950, y=80, width=465, height=625)
wrapper3_title=Label(wrapper3, text="Selected Data", bg="crimson", fg="white", font=("times new roman",30,"bold"))
wrapper3_title.grid(row=0,column=0,padx=20, pady=10)
wrapper2=Frame(win, bd=4, relief=RIDGE, bg="crimson")
wrapper2.place(x=465, y=80, width=485, height=625)
ent8=StringVar()
loaded_img = ImageTk.PhotoImage(Image.open("Amritsar.jpg"))
add_strvar = StringVar()
sub_strvar = StringVar()
pro_strvar = StringVar()
def code():
btn1.destroy()
Label2= Label(wrapper2, image=loaded_img)
Label2.grid(row=0, column=0, padx=10, pady=5, sticky='w')
def Find():
add_strvar.set(float(ent00.get())+float(ent01.get()))
sub_strvar.set(float(ent00.get())-float(ent01.get()))
pro_strvar.set(float(ent00.get())*float(ent01.get()))
ent00=Entry(wrapper, width=15)
ent00.grid(row=4, column=1, padx=10, pady=10, sticky='w')
ent01=Entry(wrapper, width=15)
ent01.grid(row=5, column=1, padx=10, pady=10, sticky='w')
lbl8=Label(wrapper, text="Add", bg="crimson", fg="white", font=("times new roman",15,"bold")).grid(row=6, column=0, padx=20, pady=10, sticky='w')
ent8=Entry(wrapper, textvariable=add_strvar, width=15, state='readonly')
ent8.grid(row=6, column=1, padx=10, pady=10, sticky='w')
lbl15=Label(wrapper, text="Subtract", bg="crimson", fg="white", font=("times new roman",15,"bold")).grid(row=7, column=0, padx=20, pady=10, sticky='w')
ent15=Entry(wrapper, textvariable=sub_strvar, width=15, state='readonly')
ent15.grid(row=7, column=1, padx=10, pady=10, sticky='w')
lbl9=Label(wrapper, text="Product", bg="crimson", fg="white", font=("times new roman",15,"bold")).grid(row=8, column=0, padx=20, pady=10, sticky='w')
ent9=Entry(wrapper, textvariable=pro_strvar, width=15, state='readonly')
ent9.grid(row=8, column=1, padx=10, pady=10, sticky='w')
btn = Button(wrapper, text = 'Calculate', command=Find, bd = '5', width=15, height=2)
btn.grid(row=11, column=1, padx=20, pady=10)
def add_img():
if add_strvar.get() == "4.0":
Label2= Label(wrapper3, image=loaded_img)
Label2.grid(row=0, column=2, padx=10, pady=5, sticky='w')
print("Move ahead")
else:
print("Try again")
btn2 = Button(wrapper, text = 'Image', command=add_img, bd = '5', width=15, height=2)
btn2.grid(row=12, column=1, padx=20, pady=10)
btn1 = Button(wrapper, text = 'OPEN CODE', command=code, bd = '5', width=20, height=2)
btn1.grid(row=11, column=1, padx=20, pady=10)
win.geometry("1400x700+250+250")
win.mainloop()
Edit 2
Code changed to work with classes:
from tkinter import *
from tkinter import ttk
from PIL import ImageTk ,Image
class ImageCalculator:
def __init__(self, img_path):
self.window = Toplevel()
self.window.geometry("1400x700+250+250")
self.mainframe = Frame(self.window)
self.mainframe.pack(expand=True, fill=BOTH)
self.bg_color = 'crimson'
frame_settings = {'master': self.mainframe, 'bd': 4,
'relief': RIDGE, 'bg': self.bg_color}
frame_names = ('left', 'center', 'right')
self.frames = {name: Frame(**frame_settings) for name in frame_names}
frame_height = 625
init_y = 80
frame_widths = {'left': 465, 'center': 485, 'right': 465}
x = 0
for name in frame_names:
frame_width = frame_widths[name]
self.frames[name].place(x=x, y=init_y, width=frame_width,
height=frame_height)
x += frame_width
self.setup_right_wrapper()
self.code_btn = self.setup_left_wrapper()
self.loaded_image = ImageTk.PhotoImage(Image.open(img_path))
self.add_strvar = StringVar()
self.sub_strvar = StringVar()
self.pro_strvar = StringVar()
def setup_left_wrapper(self) -> Button:
code_btn = Button(self.frames['left'], text='OPEN CODE', command=self.code,
bd='5', width=20, height=2)
img_btn = Button(self.frames['left'], text='Image', bd='5', width=15,
height=2, command=self.add_img)
code_btn.grid(row=11, column=1, padx=20, pady=10)
img_btn.grid(row=12, column=1, padx=20, pady=10)
return code_btn
def setup_right_wrapper(self):
right_frame_title = Label(self.frames['right'], text="Selected Data",
bg=self.bg_color, fg="white",
font=("times new roman",30,"bold"))
right_frame_title.grid(row=0, column=0, padx=20, pady=10)
def code(self):
def Find():
self.add_strvar.set(float(first_entry.get())
+ float(second_entry.get()))
self.sub_strvar.set(float(first_entry.get())
- float(second_entry.get()))
self.pro_strvar.set(float(first_entry.get())
* float(second_entry.get()))
self.code_btn.destroy()
Label2 = Label(self.frames['center'], image=self.loaded_image)
Label2.grid(row=0, column=0, padx=10, pady=5, sticky='w')
left_frame = self.frames['left']
first_entry = Entry(left_frame, width=15)
second_entry = Entry(left_frame, width=15)
# Settings of all labels
lbl_settings = {'bg': self.bg_color, 'fg': 'white',
'font': ("times new roman", 15, "bold")}
# Setting of all entry.
entry_settings = {'width': 15, 'state': 'readonly'}
add_lbl = Label(left_frame, text="Add", **lbl_settings)
add_entry = Entry(left_frame, textvariable=self.add_strvar,
**entry_settings)
sub_lbl = Label(left_frame, text="Subtract", **lbl_settings)
sub_entry = Entry(left_frame, textvariable=self.sub_strvar,
**entry_settings)
pro_lbl = Label(left_frame, text="Product", **lbl_settings)
pro_entry = Entry(left_frame, textvariable=self.pro_strvar,
**entry_settings)
calc_btn = Button(left_frame, text='Calculate', command=Find, bd='5',
width=15, height=2)
# Widget placement.
first_entry.grid(row=4, column=1, padx=10, pady=10, sticky='w')
second_entry.grid(row=5, column=1, padx=10, pady=10, sticky='w')
add_lbl.grid(row=6, column=0, padx=20, pady=10, sticky='w')
add_entry.grid(row=6, column=1, padx=10, pady=10, sticky='w')
sub_lbl.grid(row=7, column=0, padx=20, pady=10, sticky='w')
sub_entry.grid(row=7, column=1, padx=10, pady=10, sticky='w')
pro_lbl.grid(row=8, column=0, padx=20, pady=10, sticky='w')
pro_entry.grid(row=8, column=1, padx=10, pady=10, sticky='w')
calc_btn.grid(row=11, column=1, padx=20, pady=10)
def add_img(self):
if self.add_strvar.get() == "4.0":
Label2 = Label(self.frames['right'], image=self.loaded_image)
Label2.grid(row=0, column=2, padx=10, pady=5, sticky='w')
print("Move ahead")
else:
print("Try again")
def main():
img_calc = ImageCalculator('Amritsar.jpg')
mainloop()
if __name__ == "__main__":
main()
Image not showing in Tkinter Window
The difference is that in your second example, the picture was referred to only by a local variable, which went away at the end of the function. Garbage collection works a bit weirdly in Tkinter, since all of the GUI-related objects exist in the embedded Tcl interpreter, outside of Python's control.
The simple solution is to add a line like panel.image = pic
, so that a reference to the image exists for as long as the widget itself does.
Image not Rendering in Python, Tkinter, PIL
Use as below instead:
Edit: For reference as to why this is not working in the function, see here, as pointed out by @Cool Cloud. Photo "is a local variable which gets garbage collected", after leaving the function.
photo = resize_image('assests/forest01.png')
my_picture = Label(root, image=photo)
tkinter, Image does not show up unless some function added
You are using both the create_...
methods and grid
methods on your canvas
object. It won't behave as you expected.
To achieve what you want, you can create a Frame
, put your buttons in it, and then use create_window
method on your canvas:
def drawCircle():
...
shape = my_canvas1.create_oval(x1, y1, x1 + diameter, y1 + diameter+20, fill=color)
frame = tk.Frame(my_canvas1)
game1_button = tk.Button(frame, text = "Green")
game1_button.grid(row= 8, column = 3)
game1_button["command"] = lambda: messagebox.showinfo("Congratulations!", "Correct Answer!")
game2_button = tk.Button(frame, text = "Blue")
game2_button.grid(row= 8, column = 5)
game2_button["command"] = lambda: messagebox.showinfo("Sorry!", "Incorrect Answer!")
game3_button = tk.Button(frame, text = "Red")
game3_button.grid(row= 8, column = 7)
game3_button["command"] = lambda: messagebox.showinfo("Sorry", "Incorrect Answer!")
my_canvas1.create_window(200,500,window=frame)
And of course, add win.mainloop()
to the bottom of your program if you haven't already.
Related Topics
How to Flatten a Hierarchical Index in Columns
How to Get the Latest File in a Folder
Typeerror: Strptime() Argument 1 Must Be Str, Not List
Python - Remove Any Element from a List of Strings That Is a Substring of Another Element
How to Locate the Input Within Div
Shifting the Elements of an Array in Python
How Do Convert a Pandas Dataframe to Xml
How to Remove Carriage Return in a Dataframe
Use Python Extract Images from Excel Sheets
How to Print Numbers in a List That Are Less Than a Variable. Python
How to Print Just the First Letters of Each Word
List of the Most Recently Updated Files in Python
Make Alternate Letters Capital
Print a List of Space-Separated Elements
Check If a Python Script Is Already Running in Windows
Python: Assign Labels to Values in an Array
Print the Lines of a Log File Which Starts With Date Format "Yyyy-Mm-Dd" in Python