如何实现程序关闭后仍能在指定天数后触发通知(Python Tkinter)
解决方案:持久化到期任务并自动触发通知
我来帮你搞定这个问题,核心是要存储任务的到期时间而非剩余天数——毕竟程序关闭后,我们没法追踪原本的起始时间,存具体的datetime才能准确判断任务是否到期。下面是完善后的完整代码和关键解释:
完整代码实现
from tkinter import * from datetime import datetime, timedelta import pickle from tkinter import messagebox filename = "file.pk" # 存储格式:{到期datetime: [姓名, 物品, 原设定天数]} root = Tk() root.title("延迟任务通知器") # 定义界面输入变量 days_var = IntVar() item_var = StringVar() name_var = StringVar() def show_notification(name, item, days): """触发到期提醒弹窗""" messagebox.showinfo("任务到期啦!", f"姓名:{name}\n物品:{item}\n设定天数:{days}") def check_expired_tasks(): """检查并处理所有到期的任务(核心完善函数)""" try: # 尝试加载存储的任务文件,文件不存在则初始化空字典 with open(filename, "rb") as f: tasks = pickle.load(f) except FileNotFoundError: tasks = {} now = datetime.now() expired_task_times = [] # 记录需要删除的已到期任务时间 # 遍历所有任务,判断是否到期 for expire_time, task_info in tasks.items(): name, item, original_days = task_info if expire_time <= now: # 触发通知 show_notification(name, item, original_days) # 标记该任务为已处理,后续删除 expired_task_times.append(expire_time) # 移除已触发通知的任务,避免重复提醒 for task_time in expired_task_times: del tasks[task_time] # 保存更新后的任务列表回文件 with open(filename, "wb") as f: pickle.dump(tasks, f) def add_task(): """添加新的延迟任务功能(补充原代码缺失的输入逻辑)""" try: days = days_var.get() name = name_var.get().strip() item = item_var.get().strip() # 校验输入合法性 if days <= 0 or not name or not item: messagebox.showerror("输入错误", "请填写有效的姓名、物品和正整数天数!") return # 计算任务到期的具体时间 expire_time = datetime.now() + timedelta(days=days) # 加载现有任务(不存在则初始化) try: with open(filename, "rb") as f: tasks = pickle.load(f) except FileNotFoundError: tasks = {} # 添加新任务到字典 tasks[expire_time] = [name, item, days] # 保存任务到文件 with open(filename, "wb") as f: pickle.dump(tasks, f) messagebox.showinfo("成功", "任务已添加!") # 清空输入框 name_var.set("") item_var.set("") days_var.set(0) except Exception as e: messagebox.showerror("错误", f"添加任务失败:{str(e)}") # 构建GUI界面 Label(root, text="姓名:").grid(row=0, column=0, padx=5, pady=5) Entry(root, textvariable=name_var).grid(row=0, column=1, padx=5, pady=5) Label(root, text="物品:").grid(row=1, column=0, padx=5, pady=5) Entry(root, textvariable=item_var).grid(row=1, column=1, padx=5, pady=5) Label(root, text="延迟天数:").grid(row=2, column=0, padx=5, pady=5) Entry(root, textvariable=days_var).grid(row=2, column=1, padx=5, pady=5) Button(root, text="添加任务", command=add_task).grid(row=3, column=0, columnspan=2, pady=10) # 程序启动时立刻检查到期任务(核心需求实现) check_expired_tasks() root.mainloop()
关键逻辑说明
- 存储到期时间而非天数:不再存剩余天数,而是直接计算任务的到期
datetime并持久化。这样即使程序关闭,下次启动时也能准确对比当前时间判断任务是否到期。 - 启动自动检查:程序一启动就调用
check_expired_tasks(),处理所有到期任务,完美实现“中途关闭后,到期仍能触发通知”的需求。 - 清理已处理任务:到期任务触发通知后会从字典中删除,避免下次启动时重复提醒同一任务。
- 异常处理:针对文件不存在、非法输入等情况做了处理,保证程序稳定性。
使用方法
- 运行程序,输入姓名、物品和需要延迟的天数,点击「添加任务」即可保存。
- 关闭程序后,只要任务到期时间到了,下次启动程序就会自动弹出通知。
- 支持添加多个任务,程序会逐一检查并处理。
内容的提问来源于stack exchange,提问作者HEalik Tamu
相关产品推荐
相关产品推荐

