DeskTop Plans:一款纯 Python 打造的 Windows 桌面日历助手(01)

Enjoy
Enjoy
Enjoy
管理员
22
文章
0
粉丝
编程笔记评论38阅读模式
摘要DeskTop Plans 就是为这个场景而生的。它是一个不到 2000 行 Python 代码的轻量级 Windows 桌面应用,基于 tkinter 原生 GUI 框架手写而成...

前言

不知道你有没有过这样的体验:电脑桌面上摆满了各种快捷方式和临时文件,右下角的时间缩在任务栏里小到看不清,想看农历还得打开手机查,工作上设了十个待办却散落在便签、邮件、聊天记录里找不到北。有时候离开电脑前想设个定时关机,要么去命令行敲 shutdown,要么下一堆来路不明的"关机小工具"——前者门槛高,后者风险大。

DeskTop Plans:一款纯 Python 打造的 Windows 桌面日历助手(01)

这就是 DeskTop Plans 诞生的起点。它不是一个"什么都能做"的巨无霸软件,而是一个"刚好够用"的桌面伴侣:打开它,日期、农历、节气一目了然;工作计划、备忘录、纪念日统一收纳;想离开一会儿?设个倒计时,电脑自己就关了。没有账号,没有云端,没有弹窗广告,所有数据就在你自己的电脑上。

写这个应用的另一个初衷,是想证明一件事:用 Python 和 tkinter 也能做出有温度、有质感的桌面软件。 市面上太多人对 tkinter 的印象停留在"丑"、"简陋"、"只能做课后作业",但当你把导航按钮的闪烁问题用轮询方案解决掉、把进度条画成活的可变色 Canvas、把标签做成悬停上浮动画的时候,这个老框架完全可以焕发出新的生命力。

这篇文章将带你从功能、架构、技术细节到用户体验,全面了解这个不到两千行 Python 代码的桌面应用。如果你正在寻找一个轻量级桌面日历工具,或者想看看 tkinter 能做到什么程度,希望你能从中得到一些启发。

一、为什么需要一个桌面日历?

在浏览器标签里放个日历网页太轻量,开到记事本里贴日程又太简陋,打开 Outlook 或手机日历又多了好几步操作。当你窝在电脑前,想要一个始终停留在桌面上的日历 —— 能一眼看到今天几号、周几,能顺手查看工作计划和备忘录,还能看到农历和节气提醒,最好还能设个倒计时让电脑在离开后自动关机 —— 你就需要一个真正的桌面日历助理。

DeskTop Plans 就是为这个场景而生的。它是一个不到 2000 行 Python 代码的轻量级 Windows 桌面应用,基于 tkinter 原生 GUI 框架手写而成,没有引入任何第三方 UI 库。体积小、启动快、功能全,装在桌面上就是你的时间管理中心。


二、五大核心功能模块

1. 日历与农历显示

这是应用最直观的部分。主界面中央是一个超大字号(150pt)的日期数字,上方显示年月和星期,下方紧跟农历信息。农历展示不只是"几月初几"这么简单,而是完整的中文写法:"农历丙午马年五月初七",天干地支、生肖、月份、日期一气呵成。如果当天恰逢二十四节气或纪念日,农历行会以括号形式追加显示,比如"(芒种、某某生日)"。实时时钟以粗体大字显示在农历下方,每秒刷新。

日期导航支持三级粒度:日、月、年。左右三角按钮分别以大小字号区分年份按钮和月份按钮,日期按钮放在数字两侧。右键点击日期区域即可一键回到今天。

2. 工作计划管理

工作计划模块支持标题、描述、起止时间、优先级(高/中/低)、状态(进行中/已完成/已延期)和进度百分比。最出彩的是进度条的可视化设计:用 tkinter Canvas 手绘的渐变色进度条,根据完成度自动变色——进度较低时显示橙色,过半后变蓝,100% 完成时变为绿色。这比千篇一律的 ttk.Progressbar 有温度得多。

点击"添加工作计划"按钮,或在标签栏悬停"工作计划"标签,都能快速调出管理界面。每项工作都可以设置提醒提前量,到时间后系统会弹出消息框并播放提示音。

3. 备忘录

备忘录主打轻量和色彩。每条备忘包含标题、内容、颜色标签(六色调色板:米黄、浅绿、浅蓝、浅粉、浅紫、浅橙)和置顶开关。表格列表中,置顶的备忘会在标题前显示📌标记并自动排在最前。没有花哨的功能,就是记事本的核心诉求:方便、快捷、一目了然。

4. 纪念日倒计时

纪念日模块是为那些"不能忘的日子"准备的。添加纪念日时指定名称和日期(月日),系统会自动计算已经过去了多少年,并在列表中以红色醒目数字显示。悬停"纪念日"标签弹出的下拉预览按"距今天数"排序,最近的纪念日排在最前面。程序启动时,如果今天或明天有纪念日,状态栏会主动提醒:"今天就是【瑾煜生日】了,记得给TA送上祝福哦~"。

5. 电脑定时操作

这不是一个花哨功能,而是解决实用痛点。设定时、分、秒倒计时,选择"重启"或"关机",点击启动。倒计时在 Spinbox 中实时递减,期间控件锁定不可修改。计时归零后直接执行系统指令,不再弹出确认对话框——因为设计初衷就是"离开电脑前设好定时,然后就走了",如果还要再弹一个确认框,那定时功能就失去了意义。


三、核心技术实现亮点

纯 tkinter 手写 GUI

整个应用没有使用 PyQt、wxPython 或任何第三方 GUI 框架。所有界面元素 —— 包括日期选择器 DateTimePicker(7x6 网格日历)、悬停下拉预览 DropdownPreview、工作进度可视化条 —— 都是用 tkinter 原生组件手工搭建的。这意味着打包体积小(约 30MB 的 PyInstaller 单文件),无额外运行时依赖,Windows 7 到 Windows 11 都能直接运行。

导航按钮的"零闪烁"显隐方案

这是一个值得单拿出来说的技术细节。日期区域的导航按钮在默认状态下是"隐藏"的,鼠标移入时才显示。如果用传统的 <Enter> / <Leave> 事件 + place_forget() / place() 来控制,布局的微小抖动会带来闪烁。作者的解法很巧妙:

  • 按钮始终 place 在位,从不移除
  • 默认状态将按钮前景色设为与背景相同的白色(即视觉上"隐藏")
  • 通过 root.after(300) 轮询 winfo_pointerx() / winfo_pointery() 判断鼠标是否仍在日期区域内
  • 离开区域时恢复白色,进入时恢复各按钮的原始颜色

这种"AJAX 式轮询"方案彻底消除了事件驱动的闪烁问题,完全不依赖 <Leave> 事件的不可靠触发。

多线程架构

应用启动时创建两个守护线程:

  • ReminderService(每 60 秒轮询):检查工作计划截止时间提醒和纪念日提醒,触发时通过回调切回主线程弹窗
  • HotkeyHandler(事件驱动):通过 keyboard 库监听全局热键(Alt+A 关于、Alt+Q 退出),不依赖窗口焦点

主线程只负责 tkinter 事件循环和 UI 更新,线程间通过 root.after(0, callback) 安全通信。

农历与节气的实现

农历计算依赖 lunardate 库,但气象意义上的二十四节气不在农历数据库中。作者的方案是手动维护了一份 2025-2030 年的精确节气日期查表(_SOLAR_TERM_TABLES),按月份和日期匹配。虽然查表法的维护成本略高,但对于一个桌面日历应用来说,6 年覆盖时间已经足够实用,且避免了引入复杂的天文计算算法。

节日问候语的设计也很用心:状态栏在节日当天会滚动显示中文问候语,比如春节显示"新春快乐!祝您阖家幸福、万事如意!",国庆节显示"举国同庆!祝祖国繁荣昌盛!",各节气也有对应的问候文案。这些问候全部硬编码在 festival.py 的 _FESTIVAL_GREETINGS 字典中,涵盖了全部中国法定节日、农历传统节日和二十四节气。


四、数据持久化与部署适配

数据以 JSON 格式存储在 %APPDATA%\DesktopPlans\plans.json,三类数据(工作、备忘、纪念日)各自是一个数组。load_data() 函数设计了完善的前向兼容机制:新版本新增的字段(如 prioritystatuscolorpinned)会自动为旧数据补全默认值,用户升级不丢数据、不报错。

为什么把数据放到 %APPDATA% 而不是程序目录下?因为通过 Inno Setup 打包安装时,程序安装在 Program Files 下,普通用户没有写权限。%APPDATA% 是 Windows 为用户数据预留的标准漫游目录,每个用户独立存储,不会被系统清理。

打包方面,build.py 调用 PyInstaller 的 --onefile 单文件模式,配合 --windowed 隐藏控制台,输出一个干净的 .exe 文件。同时维护了 requirements.txt 声明依赖,icon.ico 提供应用图标,Inno Setup 脚本可生成标准 Windows 安装包。


五、细节见真章

这个应用最打动人的地方不是大功能,而是那些花了很多心思的小细节:

  • 标签栏的上浮动画:鼠标划过"工作计划""备忘录""纪念日"标签时,标签向上浮动几个像素并变深色,视觉反馈极佳
  • 日期数字悬停提示:鼠标停在日期数字上时,底部会从下往上飘出一条绿色提示"调整日期后,单击右键回到今天",5 秒后自动淡出——不打扰,但需要时就在
  • 全局热键:在任何窗口下按 Alt+A 打开关于,Alt+Q 退出程序,无需切回主窗口
  • 管理员权限自动处理:执行关机/重启时,如果当前没有管理员权限,会自动调用 ShellExecuteW 的 runas 提权重试,而不是直接报错
  • 30 分钟自动清除提醒:启动时显示的纪念日和工作计划提醒,不是永久占着状态栏,而是 30 分钟后自动消失——避免过时信息堆积

六、项目结构与依赖

整个项目的源代码只有 9 个 .py 文件,模块划分清晰:

main.py # 主控制器(窗口、菜单、导航、定时器、所有交互逻辑)
data_manager.py # 数据持久层(JSON 读写 + CRUD 接口)
ui_components.py # UI 组件库(下拉预览、日期选择器、表单、进度条等)
settings_dialog.py # 三大管理对话框
reminder.py # 提醒后台服务(守护线程)
about_dialog.py # 关于对话框
hotkey_handler.py # 全局热键监听
admin_utils.py # 系统关机/重启工具
festival.py # 节日、节气数据与问候语

外部依赖仅三个 Python 包:keyboard(热键)、lunardate(农历)、pygame(预留的声音支持,实际使用 winsound)。


七、适合谁用?

如果你是一个 Windows 用户,想要一个常驻桌面的日历工具,同时又不想装笨重的各类待办软件或同步服务——DeskTop Plans 就是那种"刚好够用"的选择。它不联网、不注册、不弹广告,所有数据存在本地,启动快(毫秒级),内存占用低(约 30MB),可以设为开机自启,完全融入日常桌面工作流。

对于 Python 开发者来说,这个项目也是一个很好的 tkinter 进阶参考:如何在纯 tkinter 下实现复杂 UI 交互、如何处理多线程与 UI 线程的通信、如何做数据持久化和向前兼容、如何打包成可分发的 Windows 应用——这里都有可落地的答案。


DeskTop Plans 项目开源,源码托管于本地工作目录。如有 BUG 反馈或功能建议,欢迎联系 contact@sjinyu.com。官方网站:www.sjinyu.com。

我的微信
微信扫一扫
weinxin
我的微信
微信号已复制
我的微信公众号
微信扫一扫
weinxin
我的公众号
公众号已复制
 
Enjoy
  • 本文由 Enjoy 发表于2026-05-22 16:18:37
  • 转载请务必保留本文链接:https://blog.sjinyu.com/programming/desktop-plans.html
匿名

发表评论

匿名网友
确定

拖动滑块以完成验证