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

求助:Tkinter提醒功能用time.sleep()致程序冻结,求解决方案

解决Tkinter提醒功能中的程序冻结问题

问题根源

time.sleep()会直接阻塞Tkinter的主事件循环,导致整个GUI彻底失去响应,直到休眠结束——这就是程序冻结的核心原因。Tkinter本身提供了非阻塞的延迟方案after(),无需依赖外部线程或第三方库就能解决该问题。

修复后的完整代码

from tkinter import *
from tkinter import messagebox
import customtkinter
from customtkinter import FloatEntry  # 补充原代码遗漏的导入

window = customtkinter.CTk()

def top_level():
    # 创建顶级窗口
    top = Toplevel()
    top.title("TopLevel Window")
    top.geometry('600x600')

    # 窗口初始提示文本
    msg = Message(top, text="Text on TopLevel window", width=150)
    msg.grid(row=0, column=1, padx=10, pady=12)

    # 提醒模块UI元素
    lable_remind = customtkinter.CTkLabel(top, text='Remind me about:', font=('arial', 21))  
    label_time = customtkinter.CTkLabel(top, text='In how many minutes?', font=('arial', 21))              
    lable_remind.grid(row=2, column=0, padx=10, pady=12)  
    label_time.grid(row=3, column=0, padx=10, pady=12)

    entry_box = Text(top, height=1, width=20, font=('arial', 21))
    entry_box.grid(row=2, column=1, padx=10, pady=12)

    entry_time = FloatEntry(top, font=('arial', 21))
    entry_time.grid(row=3, column=1, padx=10, pady=12)

    def show_reminder(msg_text):
        # 单独封装弹窗逻辑,供after方法调用
        messagebox.showinfo(title=None, message=msg_text)

    def reminder():
        msg = entry_box.get(1.0, "end-1c")
        time_rem = entry_time.get()
        # 转换为毫秒(after方法接受毫秒级延迟参数)
        delay_ms = int(float(time_rem) * 60 * 1000)
        # 使用Tkinter原生after实现非阻塞延迟
        top.after(delay_ms, show_reminder, msg)
        
    button_rem = customtkinter.CTkButton(top, width=120, height=40, border_width=0, corner_radius=20, text="Remind me", command=reminder)
    button_rem.grid(row=4, column=0, padx=10, pady=10)

    def exit_btn():
        top.destroy()

    btn = Button(top, text='EXIT', command=exit_btn)
    btn.grid(row=5, column=0, padx=10, pady=10)

Button(window, text="Create a TopLevel window", command=top_level).grid(row=8, column=3, padx=10, pady=10)
window.mainloop()

核心修改说明

  • 替换time.sleep()为after():该方法会在指定毫秒延迟后,将回调函数加入主事件队列,不会阻塞当前事件循环,程序可正常响应用户操作。
  • 时间单位转换:将输入的分钟数转为毫秒(分钟×60×1000),匹配after()的参数要求。
  • 拆分弹窗逻辑:把显示提醒框的操作单独封装为函数,方便after()传递参数。
  • 修复导入问题:补充FloatEntry的导入,避免运行报错。
  • 简化退出逻辑:top.destroy()后无需额外调用update(),Tkinter会自动处理窗口销毁后的更新。

关于其他方案失效的说明

如果之前尝试过threading.Timer,需注意Tkinter的GUI操作必须在主线程执行,回调中需用after()调度弹窗;而FreeCADGui的事件循环与Tkinter不兼容,因此使用Tkinter原生的after()是最可靠的解决方案。

内容的提问来源于stack exchange,提问作者Mogamad Zubair Isaacs

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 03:17:27