# clock **Repository Path**: psw456789/clock ## Basic Information - **Project Name**: clock - **Description**: No description available - **Primary Language**: Python - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-06 - **Last Updated**: 2026-08-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 梦 · 时光 — 全屏桌面时钟 > 一款沉浸式全屏桌面时钟程序,基于 Python Tkinter 构建。9 个时段自动切换背景、节气农历诗句竖排、鼠标粒子特效、模拟指针钟、温度显示、系统托盘,带完整内存防护体系。 --- ## 目录 - [项目概述](#项目概述) - [目录结构](#目录结构) - [文件说明](#文件说明) - [架构设计](#架构设计) - [功能清单](#功能清单) - [技术亮点](#技术亮点) - [环境依赖](#环境依赖) - [安装与运行](#安装与运行) - [操作指南](#操作指南) - [配置文件](#配置文件) - [日志系统](#日志系统) - [已知限制与未来规划](#已知限制与未来规划) - [许可证](#许可证) --- ## 项目概述 **梦·时光** 是一款面向 Windows 11 的全屏桌面时钟应用。它不只是显示时间——它根据一天中的 9 个时段自动切换背景图片、文字配色、粒子特效颜色,在画面左侧展示节气竖排与古典诗句,右侧展示农历日期,底部实时显示当前温度。午夜和向晚时段还会浮现模拟指针钟。 整点有弹性脉冲动画,时段切换有淡入过渡和文字闪烁,鼠标移过处有彩色粒子跟随散开。右键弹出设置面板,右上角可预览任意时段。支持系统托盘最小化、F11 全屏切换、4 小时自动重启防泄漏。 --- ## 目录结构 ``` 梦/ ├── main.py # 主程序入口,轻量协调者 ├── README.md ├── PROJECT_MEMORY.md # 项目开发笔记 ├── src/ # 源码模块 │ ├── __init__.py │ ├── my_numbers.py # 全局常量:节气数据、诗句、时段配置、坐标 │ ├── timer_manager.py # 定时器集中管理器 │ ├── bg_manager.py # 背景图管理器(双层缓存 + 渐变引擎) │ ├── time_display.py # 时钟显示模块(文字元素 + 动画) │ ├── temp_service.py # 温度异步获取服务 │ ├── settings_panel.py # 右键设置面板 │ ├── preview_window.py # 时段预览弹窗 │ ├── particle_effect.py # 鼠标粒子特效库 │ ├── clock_effect.py # 模拟指针时钟 │ └── verify_terms.py # 节气计算校验脚本 ├── 主题图片/ # 9 张时段背景 PNG │ ├── 01_欢迎(清晨).png │ ├── 02_欢迎(日出).png │ ├── 03_欢迎(朝阳).png │ ├── 04_欢迎 (正午).png │ ├── 05_欢迎(午后).png │ ├── 06_欢迎(黄昏).png │ ├── 07_欢迎(傍晚).png │ ├── 08_欢迎(向晚).png │ └── 09_欢迎(午夜).png ├── 点击音效/ # 2 个 WAV 音效 │ ├── 左键点击音效(水泡冒出).wav │ └── 右键点击音效.wav └── log/ # 运行时日志 + 配置 ├── dream_clock.log # 运行日志(INFO+) ├── dream_clock_error.log # 错误日志(WARNING+) └── settings.json # 用户设置持久化 ``` --- ## 文件说明 ### `main.py` — 主程序入口(~600 行) 全屏时钟的**轻量协调者**。负责创建窗口与画布,实例化所有子模块,绑定键盘/鼠标事件,编排主刷新循环。不包含任何业务逻辑——全部委托给子模块。 关键类:`WelcomeClock` - `running()` — 启动入口,首次运行显示新手指引 - `_start_clock()` — 初始化各模块 + 开启主循环 - `show()` — 主刷新循环(100ms),编排时间获取→背景更新→文字刷新→粒子同步→时钟显隐→温度检测→重启检查 - `over()` — 退出清理,逐层调用各模块 `stop()` + 定时器全清 + GC ### `my_numbers.py` — 全局常量与数据(~97 行) 纯数据模块,无类、无外部依赖: | 类别 | 内容 | |------|------| | 缓存配置 | `PICTURE_MAX_NUM=9` `RAW_CACHE_MAX=9` | | 定时参数 | `REFRESH_INTERVAL=100` `FADE_STEP=5` `FADE_DELAY=15` `GC_INTERVAL=30000` | | 坐标常量 | 时钟数字坐标、签名坐标(`hour_x_place=753` 等) | | 节气数据 | `SOLAR_TERMS` — 24 节气三元组 (名称, 月份, C常数) | | 节气诗句 | `TERM_POEMS` — 24 节气对应古诗上下联 | | 季节备选诗 | `SEASON_POEMS` — 春/夏/秋/冬各 2 首 | | 时段配置 | `TIME_PERIODS` — 9 时段图片/颜色/分钟区间 | | 农历表 | `LUNAR_MONTH_NAMES` `LUNAR_DAY_NAMES` | | 节气计算 | `calc_solar_term_day(year, C)` — 紫金山天文台寿星公式 | ### `timer_manager.py` — 定时器管理器(~93 行) 统一管理所有 `tkinter after()` 调度的轻量封装。解决了以下问题: - 散落各处的 `self.welcome_window.after()` 裸调用 → 集中登记 - 定时器 ID 列表无限堆积 → 60 槽位上限,超限踢旧 - 退出时逐个 `after_cancel` → 一键 `cancel_all()` 关键类:`TimerManager` - `schedule(delay_ms, callback)` — 创建并登记延时任务 - `register(tid)` — 登记外部已创建的定时器(如 ParticleEffect) - `cancel(tid)` — 取消并移除 - `cancel_all()` — 全清 ### `bg_manager.py` — 背景图管理器(~253 行) 管理 9 时段背景图片的整个生命周期: - **双层缓存**:一级 PIL 原图(RAW_CACHE_MAX=9)+ 二级缩放后 Tk 图(PICTURE_MAX_NUM=9),LRU 淘汰 - **时段匹配**:根据 `hour*60+minute` 在 `TIME_PERIODS` 中二分定位,支持预览模式覆盖 - **淡入渐变引擎**:`fade_loop()` 闭包递归,逐帧透明度递增(FADE_STEP=5, FADE_DELAY=15ms),帧间 `del temp, old_ref` + `gc.collect()` 防泄漏 - **首次特殊处理**:首次加载从纯黑占位底图淡入首张背景 - **自动恢复**:预览模式 `set_override(None)` 后下次 `update()` 自动回归真实时段 ### `time_display.py` — 时钟显示模块(~262 行) 管理画布上所有文字元素的创建、刷新与动画: - **文字元素**:时/分/秒/冒号/分隔点、签名+底衬、日期、温度、节气竖排、农历竖排、诗句两列+竖线、预览按钮 - **每帧刷新**:`refresh()` 更新所有文字内容与颜色(颜色仅在变化时更新以减少 Tk 调用) - **整点脉冲**:15 帧正弦曲线 `1.0↗1.15↘1.0` 字号缩放,约 500ms - **时段闪烁**:背景切换时文字瞬间变白 80ms 后恢复 ### `temp_service.py` — 温度服务(~80 行) 异步温度获取,不阻塞 UI 线程: - **数据源**:`wttr.in/?format=%t` - **异步**:`threading.Thread` 子线程网络请求,`after(0)` 回调主线程更新 UI - **缓存**:成功后 15 分钟刷新,失败退避:前 3 次 1 分钟,之后 5 分钟 - **回调**:`set_callback(cb)` 设置 UI 回调 ### `settings_panel.py` — 设置面板(~158 行) 右键点击弹出的半透明设置覆盖面板: - **样式**:200×145 RGBA 暗蓝灰面板,三行开关 - **开关**:粒子特效 / 左键音效 / 右键音效 - **持久化**:`load()` / `save()` 读写 `log/settings.json`,先写 `.tmp` 再 `os.replace()` 原子替换 - **新手指引标记**:`first_run` 字段,首次运行弹指引 - **交互**:鼠标移入面板显示光标+暂停粒子,移出隐藏面板+恢复 - **回调**:`on_toggle(key, new_state)` 通知主程序变更 ### `preview_window.py` — 时段预览弹窗(~147 行) 右上角"预览"按钮点击弹出 210×379 无标题栏浮窗: - **9 时段按钮**:从文件名提取时段简称 - **"回到当下"按钮**:立即还原真实时段 - **10 秒自动还原**:选中时段后 10 秒自动回到当前真实时段 - **光标同步**:`on_cursor_enter` / `on_cursor_leave` / `on_closed` 回调,弹窗关闭时自动恢复光标隐藏与粒子 ### `particle_effect.py` — 鼠标粒子特效库(~252 行) 独立的鼠标跟随粒子系统,可脱离本程序单独使用: - **生成规则**:鼠标静止 1 个/帧、移动 2 个/帧、左键加速 3 个/帧(33 帧 ≈ 1 秒) - **物理模拟**:随机角度扩散(0.4-1.8 px/帧)、生命周期 25-45 帧后消亡 - **颜色渐变**:粒子颜色向目标色混合模拟透明度(解决 Tkinter 不支持 RGBA 八位十六进制的问题) - **颜色同步**:`set_color()` 跟随时段配色,`set_blend()` 黄昏前向白混合、黄昏后向黑混合 - **生命周期**:`start()` / `stop()` / `enable()` / `disable()` 完整管理 ### `clock_effect.py` — 模拟指针时钟(~421 行) 独立的模拟指针时钟,可脱离本程序单独使用: - **表盘**:60 条秒/分钟刻度 + 12 条小时刻度 + 12 个数字 + 中心圆点 - **指针**:时/分/秒三针 + 尾部拖影(`create_polygon` 三角指针 + 反向短线拖影) - **高级分针**:平滑扫过(基于毫秒级角度计算) - **双模式**:`create_simple_clock()`(仅指针)/ `create_advanced_clock()`(含数字日期) - **闲置降帧**:窗口失焦时刷新率从 50fps 降至 10fps - **内存安全**:`stop()` 逐层释放定时器→事件绑定→画布元素→引用清空→GC ### `verify_terms.py` — 节气校验脚本(~83 行) 独立校验 `calc_solar_term_day` 对 2025/2026/2027 三年计算结果: - 日期合法性(1-31) - 同月不重复 - 12 个月全覆盖 --- ## 架构设计 ``` ┌─────────────┐ │ main.py │ ← 纯协调者(~600 行) │ WelcomeClock│ └──┬──┬──┬───┘ ┌───────────────┤ │ ├───────────────┐ ▼ ▼ ▼ ▼ ┌──────────┐ ┌────────────┐ ┌──────────────────┐ │ Timer │ │ Background │ │ TimeDisplay │ │ Manager │ │ Manager │ │ (文字+动画) │ └──────────┘ └────────────┘ └──────────────────┘ ▲ │ │ │ ┌─────┴─────┐ │ │ │ my_numbers│ │ │ │ (纯数据) │ │ │ └───────────┘ │ ├──────────────────────────────┤ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │ Settings │ │ Preview │ │ Temperature │ │ Panel │ │ Window │ │ Service │ └──────────┘ └──────────┘ └──────────────┘ ▼ ▼ ▼ ┌──────────────┐ ┌──────────────┐ ┌────────────────┐ │ Particle │ │ Clock │ │ log/ │ │ Effect │ │ Effect │ │ settings.json │ │ (独立库) │ │ (独立库) │ └────────────────┘ └──────────────┘ └──────────────┘ ``` **设计原则**: - 每个模块通过构造函数接收依赖(Canvas、TimerManager、配置),不通过全局变量耦合 - 模块间通过**回调**(`on_toggle`、`on_period_selected` 等)通知协调者,不直接修改对方状态 - 纯数据(`my_numbers.py`)零依赖,任意模块可引用 - 两个效果库(`particle_effect`、`clock_effect`)完全独立,有各自的 `start()`/`stop()` 生命周期 --- ## 功能清单 ### 🕐 核心显示 - 全屏数字钟:时/分 Times 100 bold,秒 Times 40,冒号 Times 80,分隔点 Times 50 bold - 公历日期居中显示(格式 `8月8日 星期六`) - 实时温度(wttr.in 异步获取) - 右下角签名「梦·时光」+ 半透明黑色底衬 ### 🌄 9 时段背景系统 | 时段 | 时间 | 背景图 | |------|------|--------| | 午夜 | 00:00–04:00 | 09_欢迎(午夜).png | | 清晨 | 04:00–06:00 | 01_欢迎(清晨).png | | 日出 | 06:00–08:00 | 02_欢迎(日出).png | | 朝阳 | 08:00–12:00 | 03_欢迎(朝阳).png | | 正午 | 12:00–16:00 | 04_欢迎 (正午).png | | 午后 | 16:00–20:00 | 05_欢迎(午后).png | | 黄昏 | 20:00–21:00 | 06_欢迎(黄昏).png | | 傍晚 | 21:00–21:30 | 07_欢迎(傍晚).png | | 向晚 | 21:30–24:00 | 08_欢迎(向晚).png | 每个时段配有独立的时分颜色和秒颜色,切换时淡入动画过渡。 ### 🎋 农历文化系统 - 节气竖排(STXingkai 100 号毛笔字体) - 节气对应古诗上下联,两列竖排 + 竖线分隔(KaiTi 18 号) - 非节气日按季节 + 日期奇偶轮换四季备选诗 - 农历日期竖排(AR PL UKai CN 18 号) - 节气日期使用紫金山天文台寿星公式精确计算,21 世纪误差 < 1 天 ### ✨ 鼠标粒子特效 - 鼠标经过处生成彩色圆点,向外随机扩散 - 颜色跟随时段配色,黄昏前渐隐至白色、黄昏后渐隐至黑色 - 静止 1 个/帧、移动 2 个/帧、左键加速 3 个/帧(约 1 秒) ### 🎬 动画效果 - 整点弹性脉冲:时钟数字放大 15% 正弦缩回(~500ms) - 时段切换闪烁:文字瞬间变白 80ms 后恢复 - 背景淡入过渡:逐帧透明度递增 ### ⚙️ 设置面板 - 右键弹出 200×145 半透明暗蓝灰面板 - 三行开关:粒子特效 / 左键音效 / 右键音效 - 状态持久化到 `log/settings.json` ### 🔍 时段预览 - 右上角"预览"按钮(灰色=正常,绿色=预览中) - 210×379 浮窗,9 个时段按钮 +「回到当下」 - 选中后 10 秒自动还原真实时段 ### 🔊 音效 - 左键点击:水泡冒出 WAV - 右键点击:提示音 WAV - 异步播放,可在设置面板独立开关 ### 🖥️ 窗口控制 - ESC 退出、F11 全屏/窗口切换、M 最小化到系统托盘 - 关闭按钮完整清理退出 - 系统托盘右键菜单:显示窗口 / 退出程序 ### 🛡️ 内存防护 - 30 秒周期强制 GC - 4 小时自动重启(子进程启动新实例) - 渐变帧逐帧 `del` + `gc.collect()` 释放 PIL 图像 - 设置面板 `bg_tk = None` 显式释放 PhotoImage - 退出时全量清理:定时器→画布→缓存→GC ### 📋 日志系统 - **双日志**:`dream_clock.log`(运行日志 INFO+)+ `dream_clock_error.log`(错误 WARNING+) - **自动轮转**:运行日志 1MB×3,错误日志 512KB×2 - **DEBUG 级静默**:无害异常(定时器过期、音效缺失等)不写入任何文件 ### 🆕 新手指引 - 首次运行弹出全屏半透明指引卡片 - 介绍基本操作和快捷键 - 10 秒自动消失或点击"我知道了"关闭 - 状态持久化到 `settings.json`,第二次不再弹出 --- ## 技术亮点 - **零内存泄漏**:7 条防线覆盖定时器 / Canvas / PIL / Tk 对象,长期运行内存稳定 - **原子写入**:设置文件先写 `.tmp` 再 `os.replace()`,断电不损坏 - **退避策略**:温度获取连败 3 次后从 1 分钟退避到 5 分钟 - **主循环兜底**:任何单帧异常只跳过当前帧,不导致时钟卡死 - **精确节气**:紫金山天文台寿星公式,非 ±1 天容差近似 - **模块化架构**:从 900 行 God Class 重构为 7 模块协调者架构 - **双日志分离**:运行信息与异常信息分文件存储 - **粒子颜色混合**:RGB 通道混合模拟透明度,解决 Tkinter 不支持 RGBA 八位色的问题 - **闲置降帧**:模拟时钟窗口失焦时自动降低刷新率 - **整行注释**:关键代码中英文注释覆盖,方便后期维护 --- ## 环境依赖 | 依赖 | 版本要求 | 用途 | 安装方式 | |------|:---:|------|------| | Python | ≥ 3.10 | 运行环境 | [python.org](https://www.python.org/) | | Pillow (PIL) | ≥ 10.0 | 图像加载/缩放/透明度处理 | `pip install Pillow` | | lunardate | ≥ 0.2 | 公历→农历转换 | `pip install lunardate` | | pystray | ≥ 0.19 | 系统托盘图标(可选) | `pip install pystray` | **无需额外安装**:`tkinter` `logging` `threading` `json` `urllib` `winsound` `subprocess` `math` `random` `time` `os` `gc` `sys` 均为 Python 标准库。 ### 一键安装 ```bash pip install Pillow lunardate pystray ``` ### 字体要求 以下字体未安装时程序仍可运行,但显示效果会回退到系统默认字体: | 字体 | 用途 | 备注 | |------|------|------| | Times | 时钟数字 | Windows 预装 | | Microsoft YaHei | 签名/日期/设置/预览 | Windows 预装 | | STXingkai | 节气竖排(毛笔风格) | 需单独安装"华文行楷" | | KaiTi | 诗句竖排 | Windows 预装 | | AR PL UKai CN | 农历竖排 | 需单独安装 | --- ## 安装与运行 ```bash # 1. 克隆项目 git clone cd 梦 # 2. 安装依赖 pip install Pillow lunardate pystray # 3. 运行 python main.py ``` **注意事项**: - 程序启动后自动全屏,按 ESC 退出 - 首次运行会弹出新手指引,第二次不再出现 - 日志文件位于 `log/` 目录 - 系统托盘需要 `pystray` 库,未安装时静默跳过 - 温度需要网络连接,使用 `wttr.in` 免费 API(无 API Key 要求) --- ## 操作指南 | 操作 | 方式 | |------|------| | 退出程序 | ESC 键 | | 全屏/窗口切换 | F11 键 | | 最小化到托盘 | M 键 | | 打开设置 | 右键点击画布 | | 时段预览 | 右上角"预览"按钮 | | 粒子加速 | 左键点击 | | 关闭程序 | 关闭按钮(窗口模式)或托盘菜单 | --- ## 配置文件 `log/settings.json` 结构: ```json { "particle": true, "left_sound": true, "right_sound": true, "first_run": false } ``` | 字段 | 类型 | 默认 | 说明 | |------|:---:|------|------| | `particle` | bool | true | 鼠标粒子特效开关 | | `left_sound` | bool | true | 左键水泡音效开关 | | `right_sound` | bool | true | 右键音效开关 | | `first_run` | bool | true | 首次运行标记,用于新手指引 | --- ## 日志系统 | 文件 | 级别 | 内容 | 上限 | |------|:---:|------|:---:| | `dream_clock.log` | INFO+ | 启动/退出、时段切换、设置变更、温度成功、托盘创建 | 1MB×3 | | `dream_clock_error.log` | WARNING+ | 图片缺失、温度失败、绘制异常、主循环崩溃堆栈 | 512KB×2 | --- ## 已知限制与未来规划 ### 当前限制 - 仅支持 Windows(`winsound`、`pystray` 为 Windows API) - 温度仅显示数值,无天气状况 - 背景图片需手动准备(不支持在线下载) - 时钟坐标硬编码为 1920×1080 分辨率优化(其他分辨率可用但显示位置可能偏移) ### 未来规划 - [ ] 多分辨率自适应布局 - [ ] 天气状况图标(`wttr.in` 支持 `%C` 返回天气描述) - [ ] 自定义背景图片(用户替换 `主题图片/` 文件夹) - [ ] 整点提示音 - [ ] macOS / Linux 跨平台适配 - [ ] 自定义字体大小 - [ ] 背景音乐(时段切换淡入淡出切曲) --- ## 许可证 MIT License