タスクツリーの信号機
信号機のシミュレーションを通じて、TaskTree を使用してステートマシンの動作を実装する方法を示します。
TaskTree Traffic Lightは、以下の Traffic Light サンプルの代替実装です。 Qt SCXMLおよび Qt State Machine.

このアプリケーションは、3つの主要コンポーネントで構成されています:
- 現在の状態を表示する
TrafficLightウィジェット。 - 状態遷移を制御する
TaskTreeレシピ。 - ステートマシンとUIを同期させる
GlueInterface。
以下のセクションでは、このサンプルのコードの詳細について説明します。
ヘルパー・グルークラス
GlueInterface クラスは、UI と操作ロジックをきれいに分離します。
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() | TaskTreeレシピから信号機の状態を更新する |
lightsChanged() | ライトの状態が変更されると UI に通知 |
smash()/ repair() | 障害シミュレーションと回復アクションを処理する |
ユーザが UI を操作するとき:
- pause をクリックすると、
smash()がトリガーされ、障害がシミュレートされる。 - play をクリックすると、
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 アイテムは、無限ループでその子を実行します。作業状態と故障状態を表す2つのサブグループがあります。
状態遷移ルール:
- 状態は順番に実行される。これはデフォルトのexecution mode がsequential であるためである。
- 1つの状態が完了すると、もう1つの状態が始まる。
- トランジションは、ユーザーがUIの一時停止ボタンや再生ボタンをクリックし、対応するシグナルを発することでトリガーされる。
作業」操作状態
Group は、parallel で実行される2つのタスクで構成される:
- signalAwaiterTask は
GlueInterface::smashedシグナルに接続する。シグナルがトリガーされると、タスクは直ちにDoneResult::Success を終了する。これにより、作業中の Group は実行を停止し、レシピは壊れた状態に遷移する。 - ネストされたForever タスクは4つの
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 信号に接続し、ライトは黄色のライトのオンとオフを切り替える2つの状態の間でのみ循環することです。
アプリケーションのセットアップ
メインのアプリケーション・セットアップでは、すべてのコンポーネントを作成し、接続します:
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.