tkinter实现带日期时间的时钟运行数秒后卡死无响应问题
故障原因
程序运行数秒后卡死无响应,是time()函数内重复注册定时任务导致事件队列溢出造成的:
- 每次执行
time()函数时,你先后对lbl、lbl2两个控件各调用了一次after(1000, time),单次函数运行就会新增2个1秒后触发的定时任务 - 任务数量按2的指数级增长:首次启动触发1次
time(),生成2个待执行任务;1秒后2个任务同时触发,生成4个新任务;2秒后4个任务触发生成8个……仅需7秒就会累计生成128个并发的定时回调,Tkinter的单线程事件循环根本无法处理这么多堆积的任务,直接停止响应。 - 另外你同时使用
from tkinter import *和from tkinter.ttk import *的写法,会让ttk库的同名组件覆盖tkinter原生组件,虽然不是本次卡死的直接诱因,但很容易后续出现样式、属性兼容问题,不推荐这么写。
修复方法
定时更新的逻辑只需要注册一个全局的定时回调即可,不需要给每个显示标签单独绑定after事件,修正后可稳定运行的代码如下:
from tkinter import Tk, Label from time import strftime root = Tk() root.title('Clock') root.config(bg='orange') def update_time(): # 分别更新时间、日期标签的显示内容 current_time = strftime('%I:%M:%S %p ') current_date = strftime('%A %d-%b-%Y') lbl.config(text=current_time) lbl2.config(text=current_date) # 仅注册1个定时回调,循环触发更新即可 root.after(1000, update_time) # 初始化时间、日期显示标签 lbl = Label(root, font=('calibri', 50, 'bold'), background='orange', foreground='white') lbl2 = Label(root, font=('calibri', 25, 'bold'), background='orange', foreground='white') lbl.pack(anchor='center') lbl2.pack(anchor='center') # 启动首次更新 update_time() root.mainloop()
补充说明:
after是所有tkinter控件的通用方法,不管把定时任务绑定在根窗口还是任意标签上,只要保证每次更新逻辑只注册1个下一次的定时任务,就不会出现任务堆积卡死的问题。
内容的提问来源于stack exchange,提问作者Mohamed Hussein
相关产品推荐
相关产品推荐

