当前位置: 首页 > news >正文

Python小程序:上班该做点摸鱼的事情

系统提醒

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

在这里插入图片描述
源码

# -*- coding:utf-8 -*-
"""
作者:杨桃清
日期: 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()

相关文章:

  • vue3+Nest.js项目 部署阿里云
  • 字节跳动社招面经 —— BSP驱动工程师(4)
  • vue.js中的一些事件修饰符【前端】
  • uni-app 中封装全局音频播放器
  • 深入蜂窝物联网 第四章 Cat-1 与 5G RedCap:带宽、低时延与未来趋势
  • 五、UI自动化测试05--PyTest框架
  • 【SpringBoot】基于MybatisPlus的博客管理系统(1)
  • 【Unity】使用Socket建立客户端和服务端并进行通信的例子
  • 东土科技NewPre系列智能控制器的创新之旅
  • VMware安装 银河麒麟操作系统桌面版 V10 SP1 2403
  • HotSpot的算法细节
  • 集群系统的五大核心挑战与困境解析
  • 4月28号
  • 漏洞复现清单整理-预备梳理,等待补充
  • 多维驱动:负载均衡何以成为现代系统架构的基石
  • 网络爬取需谨慎:警惕迷宫陷阱
  • Ansible安装配置
  • 代发考试战报:4月份 思科认证,华为认证,考试战报分享
  • Twitter 工作原理|架构解析|社交APP逻辑
  • 洛谷题解 | CF1979C Earning on Bets
  • 当老年人加入“行为艺术基础班”
  • 新开发银行如何开启第二个“金色十年”?
  • 复星医药换帅:陈玉卿接棒吴以芳任董事长,吴以芳改任复星国际执行总裁
  • 河北:开展领导干部任性用权等形式主义官僚主义问题专项整治
  • 法治日报调查直播间“杀熟”乱象:熟客越买越贵,举证难维权不易
  • 国内生产、境外“游一圈”再进保税仓,这些“全球购”保健品竟是假进口