I am trying to implement images into buttons in tkinter, and when i try to load it, it takes more than 5 seconds for the images and window to load.
I want it so that when next button is clicked, the images load almost instantly so that i can debug and test the code faster (without wasting 6 seconds everytime). Is there a better way (or faster) to load these images?
from tkinter import *
import math
from PIL import Image, ImageTk
import time
root = Tk()
# Tkinter stuff
root.title("Projectile motion")
root.geometry("800x500")
root.resizable(False, False)
scale_label = None
def switch():
page1.grid_forget() # Hide the welcome page
page2.grid(row=0, column=0, sticky="nsew") # Show the instructions page
page1 = Frame(root, width=800, height=500)
page2 = Frame(root, width=800, height=500, bg = "azure3")
page1.grid(row=0, column=0, sticky="nsew")
page2.grid(row=0, column=0, sticky="nsew")
# main page stuff
main_window_title = Label(page1, text="Projectile Motion Simulation", font=("Times New Roman bold", 35))
main_window_title.place(relx=0.13, rely=0.26)
main_window_button = Button(page1, text="Start", font=("Arial bold", 15), background= "#ff0000", activebackground= "#f08080", command=switch,
height=4, width=20)
main_window_button.place(relx=0.5, rely=0.6, anchor="center")
# page 2/ instructions page
welcome_text = Label(page2, text="Welcome to Projectile Motion simulation",bg = "azure3", font=("Times New Roman bold", 30))
welcome_text.place(relx = 0,rely = 0)
htp_text = Label(page2, text="How to play?", bg = "azure3" ,font=("Times New Roman", 25))
htp_text.place(relx = 0, rely = 0.1)
instruction_text = ("1) Use sliders, checkboxes, and buttons to adjust the simulation\n"
"2) Press 'Launch' button to show output values\n"
"3) Press checkboxes to show values on animation window\n"
"4) Press 'projectile 1' and 'projectile 2' to switch between projectiles \n"
"5) Press 'Explanation' button to get the theory on projectile motion\n"
"6) Press 'Quiz' button to try a quiz on projectile motion\n"
"7) Press back button to close window")
htp2_text = Label(page2, text=instruction_text,font=("Times New Roman", 20), bg = "azure3",justify='left', anchor='w')
htp2_text.place(relx = 0,rely = 0.2)
def selection_window():
selection_window = Toplevel()
selection_window.title("Selection page")
selection_window.config(width=500, height=500)
selection_window.resizable(False, False)
selection_window.bind("<Destroy>", enable_button)
click_btn= PhotoImage(file="scenario 1.png")
click_btn = click_btn.zoom(25)
click_btn = click_btn.subsample(40)
click_btn2= PhotoImage(file="scenario 2.png")
click_btn2 = click_btn2.zoom(25)
click_btn2 = click_btn2.subsample(40)
global button1
button1 = Button(selection_window, image = click_btn,command=vertical_animation)
button1.image = click_btn
button1.grid(row=0, column=0)
global button2
button2 = Button(selection_window,image = click_btn2 ,command=lambda: animation_window(1))
button2.image = click_btn2
button2.grid(row=0, column=1)
root.withdraw()
when next button is clicked, it loads for around 6 seconds]
I have changed my code from PhotoImage to Image.open. I tried it on a separate file and it works perfectly fine. But when i copy it to my code it doesn't seem to work.
this is the code in the separate file
root = tk.Tk()
root.title("Image Buttons")
# Load images
scenario1_img = Image.open("scenario 1.png")
scenario1_img = ImageTk.PhotoImage(scenario1_img)
scenario2_img = Image.open("scenario 2.png")
scenario2_img = ImageTk.PhotoImage(scenario2_img)
# Create buttons with images
button1 = tk.Button(root, image=scenario1_img, command=lambda: button_clicked(1))
button2 = tk.Button(root,image=scenario2_img , command=lambda: button_clicked(2))
# Display buttons
button1.grid(row=0, column=0, padx=10, pady=10)
button2.grid(row=0, column=1, padx=10, pady=10)
root.mainloop()
then this is my code.
def enable_button(event=None):
global next_button
next_button["state"] = "normal"
if 'button2' in globals() and button2.winfo_exists():
button2["state"] = "normal"
if 'button1' in globals() and button1.winfo_exists():
button1["state"] = "normal"
def selection_window():
next_button["state"] = "disabled"
selection_window = Toplevel()
selection_window.title("Selection page")
selection_window.config(width=500, height=500)
selection_window.resizable(False, False)
selection_window.bind("<Destroy>", enable_button)
scenario1_img = Image.open("scenario 1.png")
scenario1_img = ImageTk.PhotoImage(scenario1_img)
scenario2_img = Image.open("scenario 2.png")
scenario2_img = ImageTk.PhotoImage(scenario2_img)
global button1
button1= Button(selection_window, image=scenario1_img,command=vertical_animation)
button1.grid(row=0, column=0,padx=10, pady=10)
global button2
button2= Button(selection_window,image=scenario2_img,command=lambda: animation_window(1))
button2.grid(row=0, column=1,padx=10, pady=10)
root.withdraw()
I am not sure if it has anything to do with the enable_button() function, but when i close the window this error shows up.
Unfortunately hasn't way to do that. Creating a tkimage takes much time. And if you have a gif with hundreds of frames...
But here are some things you maybe can considerate:
.zoom()
and .subsample()
. Less work, more speed. tkimages = (tk.PhotoImage(file=img) for img in list_images_png)
button.configure(image=next(tkimages))