You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

电梯演讲倒计时程序:如何用Pillow每20秒自动重复切换图片?

问题描述

开发一款用于自我展示的电梯演讲程序,核心需求:

  • 设置2分钟倒计时
  • 每20秒自动切换展示图片,每张图片对应20秒讲解时间

目前卡在图片切换功能实现上,尝试过.after()、time.sleep()等方法,不熟悉threading线程概念。曾考虑在countdown函数中嵌套if语句,但担心代码可读性差;自行编写的image_change函数未正常工作,现有代码见下方。

问题分析与解决思路
  1. image_change未被触发:原代码中image_change函数没有被任何逻辑调用,需将其与倒计时流程关联
  2. PhotoImage引用丢失:Tkinter的PhotoImage若无持久引用,会被Python垃圾回收机制回收,导致图片无法显示
  3. 倒计时逻辑冗余:原倒计时函数分支过多,可简化为总秒数计算方式,方便判断20秒切换节点
  4. 图片管理混乱:多if判断切换图片扩展性差,改用列表存储图片路径,通过索引切换更清晰
修改后的完整代码
from tkinter import *
from PIL import Image, ImageTk

# ---------------------------- CONSTANTS ------------------------------- #
PINK = "#e2979c"
RED = "#e7305b"
GREEN = "#9bdeac"
YELLOW = "#f7f5dd"
BLUE = "#678ac2"
FONT_NAME = "Courier"
# 图片路径列表,按展示顺序添加
IMAGE_PATHS = ["paco.png", "edward.png"]  # 可自行补充更多图片
current_image_index = 0
# 总倒计时时长(秒)
TOTAL_DURATION = 120  # 2分钟=120秒

# ---------------------------- TIMER & IMAGE CHANGE ------------------------------- #

def update_timer_display(remaining_seconds):
    """格式化并更新倒计时显示"""
    minutes = remaining_seconds // 60
    seconds = remaining_seconds % 60
    timer_text.config(text=f"{minutes}:{seconds:02d}")

def countdown(remaining_seconds=TOTAL_DURATION):
    if remaining_seconds >= 0:
        update_timer_display(remaining_seconds)
        # 每20秒切换一次图片(剩余时间为20的倍数时触发,跳过初始120秒)
        if remaining_seconds < TOTAL_DURATION and remaining_seconds % 20 == 0:
            image_change()
        # 继续倒计时
        window.after(1000, countdown, remaining_seconds - 1)

def image_change():
    global current_image_index
    # 更新图片索引,循环切换
    current_image_index = (current_image_index + 1) % len(IMAGE_PATHS)
    # 加载并调整图片大小
    img = Image.open(IMAGE_PATHS[current_image_index])
    resized_img = img.resize((850, 450), Image.LANCZOS)
    photo_img = ImageTk.PhotoImage(resized_img)
    # 删除旧图片,添加新图片
    canvas.delete("image")
    canvas.create_image(450, 225, anchor=CENTER, image=photo_img, tag="image")
    # 保存图片引用,防止被垃圾回收
    canvas.current_photo = photo_img

# ---------------------------- UI SETUP ------------------------------- #
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)

# 初始化第一张图片
initial_img = Image.open(IMAGE_PATHS[0])
initial_resized = initial_img.resize((850, 450), Image.LANCZOS)
initial_photo = ImageTk.PhotoImage(initial_resized)
canvas.create_image(450, 225, anchor=CENTER, image=initial_photo, tag="image")
canvas.initial_photo = initial_photo

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)

window.mainloop()
关键修改说明
  • 图片管理:用IMAGE_PATHS列表统一管理图片路径,通过索引循环切换,后续新增图片只需添加路径即可
  • 引用保存:将PhotoImage对象赋值给canvas的属性,避免被Python垃圾回收机制回收导致图片消失
  • 倒计时简化:直接计算总剩余秒数,减少分支判断,通过remaining_seconds % 20 == 0精准触发图片切换
  • 触发逻辑:在倒计时函数中自动关联图片切换,无需额外线程,符合Tkinter单线程事件循环机制

内容的提问来源于stack exchange,提问作者MrThom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 13:20:51