任务树交通灯
演示如何通过交通灯模拟使用 TaskTree 实现状态机行为。
TaskTree Traffic Light是《Traffic Light》和《Traffic Light》中交通灯示例的替代实现。 Qt SCXML和 Qt State Machine.

该应用程序由三个主要组件组成:
- 显示当前状态的
TrafficLight部件。 - 控制状态转换的
TaskTree口诀。 - 使用户界面与状态机同步的
GlueInterface。
下文将详细介绍示例代码。
辅助胶水类
GlueInterface 类在用户界面和运行逻辑之间提供了清晰的分离。
enum class Light { Off = 0, Red = 1 << 0, Yellow = 1 << 1, Green = 1 << 2, }; Q_DECLARE_FLAGS(Lights, Light) Q_DECLARE_OPERATORS_FOR_FLAGS(Lights) class GlueInterface final : public QObject { Q_OBJECT public: // operational logic -> GUI void setLights(Lights lights) { emit lightsChanged(lights); } // GUI -> operational logic void smash() { emit smashed(); } void repair() { emit repaired(); } signals: void lightsChanged(Lights lights); void smashed(); void repaired(); };
GlueInterface 类提供以下接口方法:
| 方法 | 目的 |
|---|---|
setLights() | 更新任务树配方中的交通灯状态 |
lightsChanged() | 当灯光状态发生变化时通知用户界面 |
smash()/ repair() | 处理故障模拟和恢复操作 |
当用户与用户界面交互时:
- 单击暂停触发
smash(),模拟故障。 - 单击播放触发
repair(),恢复正常运行。
实现状态机
状态机逻辑是通过 TaskTree 配方实现的。recipe() 方法使用对GlueInterface 的引用创建该逻辑:
ExecutableItem recipe(GlueInterface &iface) { return Forever { Group { // "working" state stopOnSuccess, parallel, signalAwaiterTask(&iface, &GlueInterface::smashed), // transitions to the "broken" state Forever { switchLightsTask(&iface, Light::Red, 3s), // "red" state switchLightsTask(&iface, Light::Red | Light::Yellow, 1s), // "redGoingGreen" state switchLightsTask(&iface, Light::Green, 3s), // "green" state switchLightsTask(&iface, Light::Yellow, 1s), // "greenGoingRed" state } }, Group { // "broken" state stopOnSuccess, parallel, signalAwaiterTask(&iface, &GlueInterface::repaired), // transitions to the "working" state Forever { switchLightsTask(&iface, Light::Yellow, 1s), // "blinking" state switchLightsTask(&iface, Light::Off, 1s), // "unblinking" state } } }; }
根状态管理
顶层Forever 项在无限循环中执行其子项。它包含两个子组,分别代表工作状态和中断状态。
状态转换规则:
- 状态按顺序执行,因为默认的execution mode 是sequential 。
- 一个状态完成后,另一个状态开始。
- 当用户点击用户界面上的暂停或播放按钮,发出相应信号时,就会触发状态转换。
工作 "运行状态
工作 Group 由运行在parallel 中的两个任务组成:
- signalAwaiterTask 连接到
GlueInterface::smashed信号。如果信号被触发,任务会立即结束DoneResult::Success 。这将导致工作中的Group 停止执行,而配方则过渡到中断状态。 - 嵌套的Forever 任务由四个
switchLightsTask任务("red"、"redGoingGreen"、"green "和 "greenGoingRed")组成,以无限循环的方式执行sequentially 。
每组的stopOnSuccess 项指示它在任何子任务完成DoneResult::Success 时停止执行。
switchLightsTask 实现:
- 通过
GlueInterface::setLights()更新灯光状态。 - 使用timeoutTask 创建定时延迟。
- 在指定的持续时间内保持状态
timeout。
static Group switchLightsTask(GlueInterface *iface, Lights lights, const milliseconds &timeout) { return { onGroupSetup([iface, lights] { iface->setLights(lights); }), timeoutTask(timeout, DoneResult::Success) }; }
破碎 "运行状态
损坏的 Group 与工作的 Group 类似。唯一不同的是,它连接到GlueInterface::repaired 信号,灯光只在两个状态之间循环,切换黄灯的开和关。
应用程序设置
主应用程序设置创建并连接所有组件:
int main(int argc, char **argv) { QApplication app(argc, argv); GlueInterface iface; QTaskTree taskTree({recipe(iface)}); TrafficLight widget(iface); widget.show(); taskTree.start(); return app.exec(); }
main() 函数实例化了 QApplication、GlueInterface 、QTaskTree 和TrafficLight 对象。
为了构建taskTree 对象,我们传递了一个用iface 对象构建的recipe() 。widget 也使用传递的iface 对象。
在执行应用程序之前,main() 函数会显示TrafficLight 部件并启动任务树。
运行示例
运行示例 Qt Creator,打开Welcome 模式,并从Examples 中选择示例。更多信息,请参阅Qt Creator: 教程:构建并运行。
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.