系統提醒
上班會忘記一些自己的事,所以你需要在上班的的時候突然給你彈窗,你就知道要做啥了
源碼
這里有一個智能家居項目可以看看(開源)
# -*- coding:utf-8 -*-
"""
作者: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 mathclass ReminderApp:def __init__(self, root):self.root = rootself.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 = Trueself.start_reminder_checker()def create_default_sound(self):"""創建默認提醒聲音"""try:# 生成簡單的提示音frequency = 2000 # 頻率 (Hz)duration = 1000 # 持續時間 (ms)winsound.Beep(frequency, duration)# 保存為WAV文件import waveimport structsample_rate = 44100n_samples = int(sample_rate * duration / 1000)max_amplitude = 32767with 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(" 警告", "請先選擇一個提醒")returnindex = 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(" 警告", "請先選擇一個提醒")returnindex = 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)breaktask_time += interval# 更新下次提醒時間while task_time <= now:task_time += intervaltask["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()breaktime.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 = Falseself.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 = Noneif 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(" 錯誤", "提醒標題不能為空")returnif not message:messagebox.showerror(" 錯誤", "提醒內容不能為空")returnrepeat_interval = "5"if self.repeats_var.get():try:repeat_interval = str(int(self.interval_entry.get()))if int(repeat_interval) <= 0:raise ValueErrorexcept:messagebox.showerror(" 錯誤", "請輸入有效的重復間隔(正整數)")returnself.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()