TaskTree による信号機
信号機のシミュレーションを通じて、TaskTree を使用してステートマシンの挙動を実装する方法を示します。
「TaskTree 信号機」は、 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を操作した場合:
- 「一時停止」をクリックすると、
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 項目は、その子要素を無限ループで実行します。これには、正常状態と故障状態を表す2つのサブグループが含まれています。
状態遷移のルール:
- デフォルトのexecution mode はsequential であるため、状態は順番に実行されます。
- ある状態が完了すると、もう一方の状態が開始されます。
- 遷移は、ユーザーがUI上の「一時停止」または「再生」ボタンをクリックして、対応するシグナルを発信したときにトリガーされます。
「動作中」の操作状態
「working」Group は、parallel で実行される2つのタスクで構成されています:
- signalAwaiterTask は、
GlueInterface::smashedシグナルに接続されています。シグナルがトリガーされると、タスクは直ちにDoneResult::Success で終了します。これにより、実行中の Group の実行が停止し、レシピは「broken」状態に移行します。 - ネストされた「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 の「チュートリアル:ビルドと実行」を参照してください。
- Qt Extension for Visual Studio Code
Command Palette から「Qt: Open Qt examples 」コマンドを実行し、リストからサンプルを選択します。詳細については、Qt Extension for Visual Studio Code の「チュートリアル:ビルドと実行」を参照してください。
© 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.