Files
张宗平 83620c0cf5 教案对齐官方方案书:重写为 5 天 C++/Qt 教学设计,补齐 6 个 Qt 技术缺口示例
- docs/teaching/OUTLINE.md、slides/day1-5.html、index.html:替换此前自定义的
  4 天方案,严格对齐 docs/TRAINING_PLAN_2026.md「C++方向」Day1-5 课堂内容
  (Day6-10 为纯项目实作,不在教案范围)
- docs/teaching/examples/:官方方案书要求但仓库 p03/(wiki 抓取内容) 未覆盖的
  QSS/Model-View/JSON/QThread/QPropertyAnimation/QStateMachine 六个技术点,
  各补一个最小可运行示例 + README 教学文档,均已离屏验证跑通;手工维护,
  不属于 gen_part3.py 生成产物
- 根 CMakeLists.txt:接入 docs/teaching/examples 构建(BUILD_QT_PART 分支内),
  不改动生成器管理的 p01/p03 CMakeLists
- 任务卡改为目标/验收标准/基础知识参考三段式模板,custom.css 配套新增样式
- docs/teaching/PRETEST.md:10 题 10 分钟 C++ 摸底测验,验证教案假定的受众
  基础是否成立,并与 OUTLINE.md §0 的分层预案挂钩
2026-07-02 11:31:44 +08:00

59 lines
2.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# QStateMachine 状态机 —— 教学补充示例
> 对应方案书「C++方向 Day4」:"QT 动画框架(QPropertyAnimation)与状态机实战"
> 里的状态机部分(动画部分见 [`../property_animation/`](../property_animation/README.md))。
> 仓库 `p03/` 的 wiki 抓取内容里没有状态机相关代码,本示例是手工补写的教学
> 补充,**不属于** `tools/gen_part3.py` 的生成产物。
>
> 小提示:`QStateMachine`/`QState` 属于 **QtCore** 模块,不需要额外
> `find_package`,这也是本示例能直接放进现有 Qt5::Core 依赖里的原因。
## 概念
状态机框架用"状态 + 转换条件"描述一个对象的行为,替代手写一堆 `if/else`
`switch` 去判断"现在是什么状态、该往哪个状态跳":
- `QState` —— 一个状态,可以用 `assignProperty(obj, "属性名", 值)` 声明
"进入这个状态时,某个对象的某个属性应该变成什么值"(不用手写槽函数);
- `addTransition(信号源, 信号, 目标状态)` —— 声明"某个信号触发时,从当前状态
转换到目标状态"
- `QStateMachine` —— 持有所有状态,`setInitialState()` 指定初始状态,
`start()` 启动。
对比方案书里"棋牌类游戏""售货机"这类案例常见的手写状态机(一个枚举 + 一堆
`switch(state)`):`QStateMachine` 把"状态该长什么样"`assignProperty`)和
"什么时候切换状态"`addTransition`)分开声明,状态一多,可读性明显好于手写
`switch`
## 代码走读
见 [`qt_state_machine.cpp`](qt_state_machine.cpp)
1. 定义 `redState`/`greenState` 两个 `QState`,各自用 `assignProperty` 声明
进入该状态时按钮的文本和样式;
2. `redState->addTransition(&button, &QPushButton::clicked, greenState)`
反向同理——点击按钮在两态间来回切换(红灯 → 绿灯 → 红灯 → ……);
3. `machine.setInitialState(redState)` + `machine.start()` 启动状态机;
4. 离屏验证用 `QTimer::singleShot` 模拟一次 `button.click()`,观察状态确实从
红灯切换到绿灯。
## 验证方式
```bash
QT_QPA_PLATFORM=offscreen tools/run_qt.sh qt_state_machine
```
## 练习方向(供任务卡引用)
- 加一个 `yellowState`(黄灯),改成红→绿→黄→红的三态循环,体会状态数量增加
`QStateMachine` 写法的可读性优势;
- 给某个状态加一个定时器转换:`redState->addTransition(timer, &QTimer::timeout, greenState)`
实现"红灯持续 3 秒后自动变绿灯"(不需要用户点击)。
## 参考
- 本仓库对照:[`p03/ch06/modal_dialog.cpp`](../../../../p03/ch06/modal_dialog.cpp)
等对话框示例里也有"根据用户操作决定下一步界面"的朴素状态切换,可以对比
"手写 if/else" 和 "QStateMachine 声明式写法" 的差异;
- Qt 官方文档:*The State Machine Framework*doc.qt.io,选读·需联网)