跳转至

11-综合练习:做一个小型桌面工具(番茄钟)

目录页:见 Qt 教程目录

目标

  • 把前面章节串起来:布局 + 信号槽 + 定时器 +(可选)资源
  • 做一个“最小可用”的桌面工具:番茄钟倒计时
  • 学会按模块拆分:UI、状态、业务逻辑分开写

先决知识(可选)

  • Widget 与布局(见 05 章)
  • 信号与槽(见 04 章)
  • 资源系统(可选,见 06 章)

1. 番茄钟要解决什么:可视化倒计时 + 提醒

功能清单(先做最小可用):

  1. 设置分钟数(默认 25)
  2. Start:开始倒计时
  3. Pause:暂停
  4. Reset:回到初始时间
  5. 显示剩余时间(mm:ss)

加分项(做完最小可用再加): - 倒计时结束弹出提示框 - 托盘图标/声音提醒 - 预设:25/5/15 分钟一键切换


2. 结构怎么拆:三块就够用

建议拆成三层(新手容易维护):

  1. 状态(State):剩余秒数、是否运行、初始秒数
  2. 逻辑(Logic):start/pause/reset/tick
  3. 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/60ss = 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 会更好改、更不乱
  • 下一个提升方向:把数据保存到本地、加入托盘、加入更复杂的界面与动画