系统提醒
上班会忘记一些自己的事,所以你需要在上班的的时候突然给你弹窗,你就知道要做啥了

源码
这里有一个智能家居项目可以看看(开源)
"""
作者:YTQ
日期: 2025年04日29 21:51:24
"""
import datetime
import time
import threading
import winsound
import tkinter as tk
from tkinter import ttk, messagebox
from plyer import notification
import json
import os
import math
class ReminderApp:
def __init__(self, root):
self.root = root
self.root.title(" 定时任务提醒系统")
self.root.geometry("500x400")
self.tasks = []
self.load_tasks()
self.sound_file = "reminder.wav"
if not os.path.exists(self.sound_file):
self.create_default_sound()
self.create_widgets()
self.check_reminders_active = True
self.start_reminder_checker()
def create_default_sound(self):
"""创建默认提醒声音"""
try:
frequency = 2000
duration = 1000
winsound.Beep(frequency, duration)
import wave
import struct
sample_rate = 44100
n_samples = int(sample_rate * duration / 1000)
max_amplitude = 32767
with wave.open(self.sound_file, 'w') as f:
f.setparams((1, 2, sample_rate, n_samples, 'NONE', 'not compressed'))
for i in range(n_samples):
value = int(max_amplitude * (0.5 * (1 +
math.sin(2 * math.pi * frequency * i / sample_rate))))
data = struct.pack('<h', value)
f.writeframesraw(data)
except:
messagebox.showwarning(" 警告", "无法创建默认声音文件,将使用系统蜂鸣声")
def create_widgets(self):
"""创建界面组件"""
main_frame = ttk.Frame(self.root, padding="10")
main_frame.pack(fill=tk.BOTH, expand=True)
self.task_listbox = tk.Listbox(main_frame, height=10, selectmode=tk.SINGLE)
self.task_listbox.pack(fill=tk.BOTH, expand=True, pady=(0, 10))
self.refresh_task_list()
scrollbar = ttk.Scrollbar(main_frame, orient="vertical")
scrollbar.config(command=self.task_listbox.yview)
self.task_listbox.config(yscrollcommand=scrollbar.set)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
button_frame = ttk.Frame(main_frame)
button_frame.pack(fill=tk.X, pady=(10, 0))
ttk.Button(button_frame, text="添加提醒", command=self.add_reminder).pack(side=tk.LEFT, padx=5)
ttk.Button(button_frame, text="编辑提醒", command=self.edit_reminder).pack(side=tk.LEFT, padx=5)
ttk.Button(button_frame, text="删除提醒", command=self.delete_reminder).pack(side=tk.LEFT, padx=5)
self.status_var = tk.StringVar()
self.status_var.set(" 就绪")
ttk.Label(main_frame, textvariable=self.status_var, relief=tk.SUNKEN).pack(fill=tk.X, pady=(10, 0))
def add_reminder(self):
"""添加新提醒"""
dialog = ReminderDialog(self.root, "添加新提醒")
if dialog.result:
self.tasks.append({
"title": dialog.result["title"],
"message": dialog.result["message"],
"time": dialog.result["time"].strftime("%Y-%m-%d %H:%M"),
"repeats": dialog.result["repeats"],
"repeat_interval": dialog.result["repeat_interval"]
})
self.save_tasks()
self.refresh_task_list()
self.status_var.set(f" 已添加新提醒: {dialog.result['title']}")
def edit_reminder(self):
"""编辑现有提醒"""
selected = self.task_listbox.curselection()
if not selected:
messagebox.showwarning(" 警告", "请先选择一个提醒")
return
index = selected[0]
task = self.tasks[index]
time_obj = datetime.datetime.strptime(task["time"], "%Y-%m-%d %H:%M")
dialog = ReminderDialog(
parent=self.root,
dialog_title="编辑提醒",
title_text=task["title"],
message=task["message"],
time=time_obj,
repeats=task["repeats"],
repeat_interval=task["repeat_interval"]
)
if dialog.result:
self.tasks[index] = {
"title": dialog.result["title"],
"message": dialog.result["message"],
"time": dialog.result["time"].strftime("%Y-%m-%d %H:%M"),
"repeats": dialog.result["repeats"],
"repeat_interval": dialog.result["repeat_interval"]
}
self.save_tasks()
self.refresh_task_list()
self.status_var.set(f" 已更新提醒: {dialog.result['title']}")
def delete_reminder(self):
"""删除提醒"""
selected = self.task_listbox.curselection()
if not selected:
messagebox.showwarning(" 警告", "请先选择一个提醒")
return
index = selected[0]
task_title = self.tasks[index]["title"]
if messagebox.askyesno(" 确认", f"确定要删除提醒 '{task_title}' 吗?"):
del self.tasks[index]
self.save_tasks()
self.refresh_task_list()
self.status_var.set(f" 已删除提醒: {task_title}")
def refresh_task_list(self):
"""刷新任务列表显示"""
self.task_listbox.delete(0, tk.END)
for task in self.tasks:
repeat_text = ""
if task["repeats"]:
interval = task["repeat_interval"]
repeat_text = f" (每{interval}分钟重复)"
self.task_listbox.insert(tk.END,
f"{task['title']} - {task['time']}{repeat_text}")
def load_tasks(self):
"""从文件加载任务"""
if os.path.exists("reminders.json"):
try:
with open("reminders.json", "r") as f:
self.tasks = json.load(f)
except:
self.tasks = []
messagebox.showwarning(" 警告", "无法加载提醒列表,已创建新列表")
def save_tasks(self):
"""保存任务到文件"""
with open("reminders.json", "w") as f:
json.dump(self.tasks, f, indent=2)
def start_reminder_checker(self):
"""启动提醒检查线程"""
def check_reminders():
while self.check_reminders_active:
now = datetime.datetime.now()
for task in self.tasks:
task_time = datetime.datetime.strptime(task["time"], "%Y-%m-%d %H:%M")
if task["repeats"]:
interval = datetime.timedelta(minutes=int(task["repeat_interval"]))
while task_time <= now:
if task_time + datetime.timedelta(seconds=30) >= now:
self.show_reminder(task)
break
task_time += interval
while task_time <= now:
task_time += interval
task["time"] = task_time.strftime("%Y-%m-%d %H:%M")
self.save_tasks()
else:
if task_time <= now <= task_time + datetime.timedelta(seconds=30):
self.show_reminder(task)
self.tasks.remove(task)
self.save_tasks()
self.refresh_task_list()
break
time.sleep(1)
threading.Thread(target=check_reminders, daemon=True).start()
def show_reminder(self, task):
"""显示提醒通知"""
notification.notify(
title=task["title"],
message=task["message"],
timeout=10
)
try:
if os.path.exists(self.sound_file):
winsound.PlaySound(self.sound_file, winsound.SND_FILENAME)
else:
winsound.Beep(2000, 1000)
except:
pass
self.root.after(0, lambda: messagebox.showinfo(task["title"], task["message"]))
def on_closing(self):
"""关闭窗口时清理资源"""
self.check_reminders_active = False
self.root.destroy()
class ReminderDialog(tk.Toplevel):
"""提醒设置对话框"""
def __init__(self, parent, dialog_title="设置提醒", title_text="", message="",
time=None, repeats=False, repeat_interval="5"):
super().__init__(parent)
self.title(dialog_title)
self.result = None
if time is None:
time = datetime.datetime.now() + datetime.timedelta(minutes=5)
main_frame = ttk.Frame(self, padding="10")
main_frame.pack(fill=tk.BOTH, expand=True)
ttk.Label(main_frame, text="提醒标题:").grid(row=0, column=0, sticky="w", pady=5)
self.title_entry = ttk.Entry(main_frame, width=30)
self.title_entry.grid(row=0, column=1, sticky="ew", pady=5)
self.title_entry.insert(0, title_text)
ttk.Label(main_frame, text="提醒内容:").grid(row=1, column=0, sticky="nw", pady=5)
self.message_text = tk.Text(main_frame, width=30, height=4)
self.message_text.grid(row=1, column=1, sticky="ew", pady=5)
self.message_text.insert("1.0", message)
time_frame = ttk.Frame(main_frame)
time_frame.grid(row=2, column=0, columnspan=2, sticky="ew", pady=5)
ttk.Label(time_frame, text="提醒时间:").pack(side=tk.LEFT)
self.time_var = tk.StringVar(value=time.strftime("%Y-%m-%d %H:%M"))
self.time_entry = ttk.Entry(time_frame, textvariable=self.time_var, width=16)
self.time_entry.pack(side=tk.LEFT, padx=5)
repeat_frame = ttk.Frame(main_frame)
repeat_frame.grid(row=3, column=0, columnspan=2, sticky="ew", pady=5)
self.repeats_var = tk.BooleanVar(value=repeats)
self.repeat_check = ttk.Checkbutton(
repeat_frame, text="重复提醒", variable=self.repeats_var,
command=self.toggle_repeat)
self.repeat_check.pack(side=tk.LEFT)
ttk.Label(repeat_frame, text="间隔(分钟):").pack(side=tk.LEFT, padx=(10, 5))
self.interval_entry = ttk.Entry(repeat_frame, width=5)
self.interval_entry.pack(side=tk.LEFT)
self.interval_entry.insert(0, repeat_interval)
self.toggle_repeat()
button_frame = ttk.Frame(main_frame)
button_frame.grid(row=4, column=0, columnspan=2, pady=(10, 0))
ttk.Button(button_frame, text="确定", command=self.on_ok).pack(side=tk.RIGHT, padx=5)
ttk.Button(button_frame, text="取消", command=self.destroy).pack(side=tk.RIGHT)
self.transient(parent)
self.grab_set()
self.wait_window(self)
def toggle_repeat(self):
"""切换重复设置状态"""
if self.repeats_var.get():
self.interval_entry.config(state=tk.NORMAL)
else:
self.interval_entry.config(state=tk.DISABLED)
def on_ok(self):
"""确认设置"""
try:
time_obj = datetime.datetime.strptime(self.time_var.get(), "%Y-%m-%d %H:%M")
title = self.title_entry.get().strip()
message = self.message_text.get("1.0", "end-1c").strip()
if not title:
messagebox.showerror(" 错误", "提醒标题不能为空")
return
if not message:
messagebox.showerror(" 错误", "提醒内容不能为空")
return
repeat_interval = "5"
if self.repeats_var.get():
try:
repeat_interval = str(int(self.interval_entry.get()))
if int(repeat_interval) <= 0:
raise ValueError
except:
messagebox.showerror(" 错误", "请输入有效的重复间隔(正整数)")
return
self.result = {
"title": title,
"message": message,
"time": time_obj,
"repeats": self.repeats_var.get(),
"repeat_interval": repeat_interval
}
self.destroy()
except ValueError:
messagebox.showerror(" 错误", "请输入有效的时间格式(YYYY-MM-DD HH:MM)")
if __name__ == "__main__":
root = tk.Tk()
app = ReminderApp(root)
root.protocol("WM_DELETE_WINDOW", app.on_closing)
root.mainloop()