如何使用Python的tkinter在加载进度条时同步播放GIF动画
核心问题
- tkinter的所有GUI操作和主循环必须运行在主线程,原有代码把GIF播放逻辑放在子线程执行,不符合tkinter的线程安全要求,导致GUI无法正常渲染
- 缺失
time、sys模块导入,没有实现GIF逐帧切换、窗口自动关闭的逻辑
修复后完整代码
import threading import tkinter import time import sys # 预加载GIF所有帧 gif_frames = [tkinter.PhotoImage(file='./myScripts/M-95.gif', format=f'gif -index {i}') for i in range(10)] load_complete = False # 进度条加载完成标记 max_play_time = 4000 # GIF最长播放时间4秒 def update_gif(label, frame_idx=0): global load_complete # 进度条加载完成 或 达到最长播放时间,关闭窗口 if load_complete or frame_idx * 100 >= max_play_time: # 每帧间隔100ms,可自行调整 root.destroy() return # 切换当前帧 label.config(image=gif_frames[frame_idx]) # 计算下一帧索引,循环播放 next_idx = (frame_idx + 1) % len(gif_frames) label.after(100, update_gif, label, next_idx) def loadingAnimation(): global load_complete animation = ["[■□□□□□□□□□]","[■■□□□□□□□□]", "[■■■□□□□□□□]", "[■■■■□□□□□□]", "[■■■■■□□□□□]", "[■■■■■■□□□□]", "[■■■■■■■□□□]", "[■■■■■■■■□□]", "[■■■■■■■■■□]", "[■■■■■■■■■■]"] for i in range(len(animation)): sys.stdout.write("\r | Loading..." + animation[i]) sys.stdout.flush() time.sleep(0.4) # 标记进度条加载完成 load_complete = True # 初始化320x320 GUI窗口 root = tkinter.Tk() root.geometry("320x320") # 窗口居中显示 root.eval('tk::PlaceWindow . center') # 隐藏标题栏和边框,不需要可以删除此行 root.overrideredirect(True) # 创建显示GIF的标签 gif_label = tkinter.Label(root) gif_label.pack(fill=tkinter.BOTH, expand=True) # 启动GIF播放 update_gif(gif_label) # 启动进度条子线程 loading_thread = threading.Thread(target=loadingAnimation, daemon=True) loading_thread.start() # 启动tkinter主循环 root.mainloop() loading_thread.join()
逻辑说明
- 线程逻辑反转:符合tkinter运行要求,GUI操作全部放在主线程,耗时的进度条输出逻辑放在子线程执行,避免阻塞GUI渲染
- 双关闭规则:进度条加载完成、最长播放4秒两个条件哪个先触发,就自动关闭GIF窗口,完全匹配需求
- GIF帧切换用tkinter原生
after方法实现,无阻塞播放流畅 - 窗口默认居中显示,不需要无边框效果删除
root.overrideredirect(True)即可
内容的提问来源于stack exchange,提问作者BJonas88
相关产品推荐
相关产品推荐

