I'm trying to make a little elevator pitch program as a way to present myself. The program counts down from 2 minutes, and I'd like it to automatically update with a picture every 20 seconds. This allows me to give details about the shown picture for 20 seconds, and then move on.
However, I am stuck on the image switching part. I've looked at .after(), .time(), .sleep() and looked at threading - which is still an unknown and rough concept for me.
So far, this is where I am at.
Currently, my thoughts are all over the place and I'm not sure which way would work (best). I've considered a nested if-statement inside the countdown function, but that would make everything very hard to read, I think.
I've considered setting up a second function which would handle the image changing, of which you can see an early and not working example below.
from tkinter import *
from tkinter import ttk
from PIL import Image, ImageTk
import math
import time
import datetime
# ---------------------------- CONSTANTS ------------------------------- #
PINK = "#e2979c"
RED = "#e7305b"
GREEN = "#9bdeac"
YELLOW = "#f7f5dd"
BLUE = "#678ac2"
FONT_NAME = "Courier"
REPEATS = 0
# ---------------------------- TIMER MECHANISM ------------------------------- #
def countdown(total_seconds=60, total_minutes=2):
if total_seconds == 60:
total_seconds -= 1
total_minutes -= 1
timer_text.config(text=f"{total_minutes}:{total_seconds}")
window.after(1000, countdown, total_seconds, total_minutes)
elif total_seconds == 1 and total_minutes != 0:
total_seconds = 59
timer_text.config(text=f"{total_minutes}:00")
window.after(1000, countdown, total_seconds, total_minutes)
elif total_seconds == 0 and total_minutes > 0:
total_seconds = 59
total_minutes -= 1
timer_text.config(text=f"{total_minutes}:{total_seconds}")
window.after(1000, countdown, total_seconds, total_minutes)
elif 11 > total_seconds > 0:
total_seconds -= 1
timer_text.config(text=f"{total_minutes}:0{total_seconds}")
window.after(1000, countdown, total_seconds, total_minutes)
elif total_seconds == 0 and total_minutes == 0:
pass
else:
total_seconds -= 1
timer_text.config(text=f"{total_minutes}:{total_seconds}")
window.after(1000, countdown, total_seconds, total_minutes)
def image_change():
global REPEATS
REPEATS = 1
if REPEATS == 1:
second_img = (Image.open("edward.png"))
second_resized_image = second_img.resize((850, 450), Image.LANCZOS)
second_new_image = ImageTk.PhotoImage(second_resized_image)
canvas.create_image(450, 225, anchor=CENTER, image=second_new_image)
elif REPEATS == 2:
print("repeats worked once")
else:
print("Error with repeats")
# ---------------------------- UI SETUP ------------------------------- #
# Create window & canvas
window = Tk()
window.title("Elevator Pitch")
window.geometry("900x600")
window.configure(bg=BLUE)
canvas = Canvas(window, width=900, height=500, bg=BLUE)
canvas.grid(column=1, row=1)
img = (Image.open("paco.png"))
resized_image = img.resize((850, 450), Image.LANCZOS)
new_image = ImageTk.PhotoImage(resized_image)
canvas.create_image(450, 225, anchor=CENTER, image=new_image)
# Create timer text & button
timer_text = Label(window, text="2:00", font=(FONT_NAME, 35, "bold"), bg=BLUE)
timer_text.grid(column=1, row=2)
start_button = Button(text="Start", command=countdown)
start_button.grid(column=1, row=3)
# Create new images
window.mainloop()
CodePudding user response:
You can change the image when the countdown is divisible by 20 seconds. I've simplified your countdown so it just uses the number of seconds to make this easier. I've added the load_image
function to delete the existing image if there is one and then show the next one. It uses pop
to get and remove the first images from the IMAGES
array.
from tkinter import *
from tkinter import ttk
from PIL import Image, ImageTk
import math
import time
import datetime
# ---------------------------- CONSTANTS ------------------------------- #
PINK = "#e2979c"
RED = "#e7305b"
GREEN = "#9bdeac"
YELLOW = "#f7f5dd"
BLUE = "#678ac2"
FONT_NAME = "Courier"
# Changes start here
IMAGES = ["first.png", "second.png", "third.png", ...] # Put your image file paths here
CURRENT_IMAGE = None
CURRENT_PHOTOIMAGE = None
# ---------------------------- TIMER MECHANISM ------------------------------- #
def countdown(total_seconds=120):
total_seconds -= 1
minutes, seconds = divmod(total_seconds, 60)
timer_text.config(text = f"{minutes}:{seconds:02d}")
if total_seconds % 20 == 0 and IMAGES: # Will be called every 20 seconds if there are any images left
load_image()
if total_seconds > 0:
window.after(1000, countdown, total_seconds)
def load_image():
global CURRENT_IMAGE, CURRENT_PHOTOIMAGE
if IMAGES:
if CURRENT_IMAGE:
canvas.delete(CURRENT_IMAGE)
img = Image.open(IMAGES.pop(0))
resized_image = img.resize((850, 450), Image.LANCZOS)
# It's important to keep a reference to the PhotoImage or it'll get garbage collected
CURRENT_PHOTOIMAGE = ImageTk.PhotoImage(resized_image)
CURRENT_IMAGE = canvas.create_image(450, 225, anchor=CENTER, image=CURRENT_PHOTOIMAGE)
# ---------------------------- UI SETUP ------------------------------- #
# Create window & canvas
window = Tk()
window.title("Elevator Pitch")
window.geometry("900x600")
window.configure(bg=BLUE)
canvas = Canvas(window, width=900, height=500, bg=BLUE)
canvas.grid(column=1, row=1)
load_image()
# Changes end here
timer_text = Label(window, text="2:00", font=(FONT_NAME, 35, "bold"), bg=BLUE)
timer_text.grid(column=1, row=2)
start_button = Button(text="Start", command=countdown)
start_button.grid(column=1, row=3)
# Create new images
window.mainloop()