Tkinter药品提醒程序问题:闹钟响后Snooze按钮不显示
解决Tkinter用药提醒程序中Snooze按钮不显示的问题
问题根源
你的代码里有两个核心问题导致Snooze按钮无法正常显示:
sd.wait()是阻塞式调用,会直接卡住Tkinter的主事件循环,必须等音频完全播放完毕才会执行create_snooze_button(),而且阻塞期间界面根本无法更新渲染按钮。- 每次触发闹钟都会创建新的Snooze按钮,不仅冗余,还会导致界面控件混乱。
修正方案
下面是修复后的完整代码,关键修改点已标注:
import tkinter as tk import sounddevice as sd import soundfile as sf stop = False interval = 0 # 初始化全局间隔变量 original_interval = 0 # 保存用户初始设定的间隔,用于Stop按钮重置 def start_alarm(): global interval, original_interval, stop stop = False original_interval = int(entry.get()) interval = original_interval time_left.config(text=f"{interval} seconds left") # 隐藏Snooze按钮(如果之前显示的话) snooze_button.pack_forget() countdown() def stop_alarm(): global stop stop = True sd.stop() # 隐藏Snooze按钮 snooze_button.pack_forget() start_alarm() def snooze_alarm(): global stop, interval stop = True sd.stop() interval = 600 # 直接设置为10分钟(600秒),符合需求逻辑 time_left.config(text=f"{interval} seconds left") # 隐藏Snooze按钮 snooze_button.pack_forget() countdown() def countdown(): global interval, stop if interval > 0 and not stop: interval -= 1 time_left.config(text=f"{interval} seconds left") time_left.after(1000, countdown) elif not stop: play_alarm() def play_alarm(): data, fs = sf.read('alarm.wav', dtype='float32') sd.play(data, fs) # 用Tkinter的after循环检查音频状态,替代阻塞的sd.wait() root.after(100, check_alarm_status) def check_alarm_status(): if sd.get_stream().active: # 音频还在播放,继续定时检查 root.after(100, check_alarm_status) else: # 音频播放完毕,显示Snooze按钮 snooze_button.pack() root = tk.Tk() root.title("Medicine Reminder") label = tk.Label(root, text="Enter time interval (in seconds):") label.pack() entry = tk.Entry(root) entry.pack() start_button = tk.Button(root, text="Start", command=start_alarm) start_button.pack() stop_button = tk.Button(root, text="Stop", command=stop_alarm) stop_button.pack() # 提前创建Snooze按钮,默认隐藏,避免重复创建 snooze_button = tk.Button(root, text="Snooze", command=snooze_alarm) snooze_button.pack_forget() time_left = tk.Label(root, text="") time_left.pack() root.mainloop()
关键修改说明
- 替换阻塞的
sd.wait():改用root.after()循环检查音频播放状态,彻底避免卡住Tkinter主事件循环,保证界面能实时更新。 - 提前创建并控制Snooze按钮:一开始就完成按钮创建,用
pack()/pack_forget()控制显示和隐藏,不会重复生成控件。 - 修正Snooze逻辑:把
interval +=600改成interval =600,因为闹钟触发时interval已经归零,直接设置为10分钟才符合需求。 - 新增初始间隔保存:用
original_interval存储用户最初设置的时长,Stop按钮触发时能准确重置回初始值,避免原代码中重新读取输入框的潜在问题。 - 全局变量初始化:提前初始化核心全局变量,避免未定义报错。
内容的提问来源于stack exchange,提问作者Legend_recalls
相关产品推荐
相关产品推荐

