11-综合练习:做一个小型桌面工具(番茄钟)¶
目录页:见 Qt 教程目录
目标¶
- 把前面章节串起来:布局 + 信号槽 + 定时器 +(可选)资源
- 做一个“最小可用”的桌面工具:番茄钟倒计时
- 学会按模块拆分:UI、状态、业务逻辑分开写
先决知识(可选)¶
- Widget 与布局(见 05 章)
- 信号与槽(见 04 章)
- 资源系统(可选,见 06 章)
1. 番茄钟要解决什么:可视化倒计时 + 提醒¶
功能清单(先做最小可用):
- 设置分钟数(默认 25)
- Start:开始倒计时
- Pause:暂停
- Reset:回到初始时间
- 显示剩余时间(mm:ss)
加分项(做完最小可用再加): - 倒计时结束弹出提示框 - 托盘图标/声音提醒 - 预设:25/5/15 分钟一键切换
2. 结构怎么拆:三块就够用¶
建议拆成三层(新手容易维护):
- 状态(State):剩余秒数、是否运行、初始秒数
- 逻辑(Logic):start/pause/reset/tick
- UI:按钮、标签、输入框,只做显示与触发逻辑
你可以把它类比成: - UI 是“面板按钮” - Logic 是“控制电路” - State 是“电路里的电压/开关状态”
3. 最小实现:用 QTimer 每秒 tick 一次¶
- 专业名称:QTimer(定时器)
- 类比:一个闹钟,每隔一段时间响一次
- 作用:做倒计时、轮询、动画驱动(简单场景)
- 规则/坑点:QTimer 在主线程跑很适合轻量任务;tick 里不要做重活
你需要的核心数据:
- int initialSeconds
- int remainingSeconds
- bool running
核心逻辑(伪代码):
start:
if remainingSeconds <= 0: remainingSeconds = initialSeconds
running = true
timer.start(1000)
pause:
running = false
timer.stop()
reset:
running = false
timer.stop()
remainingSeconds = initialSeconds
onTimeout:
if remainingSeconds > 0: remainingSeconds -= 1
if remainingSeconds == 0:
timer.stop()
running = false
show "done"
4. UI 怎么做:一个输入 + 一个时间显示 + 三个按钮¶
控件建议: - QLineEdit(输入分钟数) - QLabel(显示剩余时间) - QPushButton x3(Start/Pause/Reset) - QHBoxLayout/QVBoxLayout(排版)
显示时间(mm:ss)的关键点:
- 你手里是秒数
- 显示要做格式化:mm = s/60,ss = s%60,不足两位补 0
5. 常见坑¶
-
错误:把分钟当秒用,倒计时速度不对
结果:25 分钟变 25 秒
正确:分钟 * 60 才是秒 -
错误:多次点击 Start 导致多个计时逻辑叠加
结果:倒计时变快
正确:Start 前先检查running;或者每次 Start 先 stop 再 start -
错误:在 timeout 里写了重逻辑(读文件/网络/大循环)
结果:UI 卡顿
正确:tick 里只做轻量更新
小练习(把项目做得更像“真工具”)¶
练习 1:结束提示¶
- 题目:倒计时结束弹出 QMessageBox 提示
- 输入/输出:弹窗显示“时间到”
- 约束:必须在倒计时到 0 的那一刻触发
- 提示:别每次 tick 都弹,只弹一次
- 目标:练“状态变化触发一次性事件”
练习 2:预设按钮¶
- 题目:加三个预设按钮:25/5/15 分钟
- 输入/输出:点击后立刻更新输入框与剩余时间
- 约束:如果正在运行,先暂停再切换
- 提示:把“切换时间”写成一个函数复用
- 目标:练“把重复逻辑抽出来”
练习 3:资源美化(可选)¶
- 题目:用 qrc 加一个图标,设置为窗口图标
- 输入/输出:窗口有自定义图标
- 约束:必须使用
:/... - 提示:见 06 章
- 目标:把资源系统用到真实项目里
小结¶
- 你已经能用 Qt 写一个“可用的小工具”:输入 → 逻辑 → UI 更新
- 项目拆成 State/Logic/UI 会更好改、更不乱
- 下一个提升方向:把数据保存到本地、加入托盘、加入更复杂的界面与动画