ステートマシンのインスタンス化

動的に作成されたステートマシンもコンパイルされたステートマシンも、同じように振る舞い、同じプロパティ、ステート、データモデルなどを持つ。インスタンス化の方法が異なるだけです。C++でSCXMLファイルから動的にステートマシンを作成するには、次のようにします:

auto *stateMachine = QScxmlStateMachine::fromFile("MyStatemachine.scxml");

または、QMLを使用します:

import QtScxml

Item {
    property StateMachine stateMachine: scxmlLoader.stateMachine

    StateMachineLoader {
        id: scxmlLoader
        source: "statemachine.scxml"
    }
}

コンパイルされたステートマシンは、C++のオブジェクトと同じようにインスタンス化することができます:

auto *stateMachine = new MyStatemachine;

あるいは、次のようにします:

MyStatemachine stateMachine;

コンパイルされたステートマシンをQMLで使用するには、それをQMLの型として登録します:

struct MyStateMachineRegistration {
    Q_GADGET
    QML_NAMED_ELEMENT(MyStateMachine)
    QML_FOREIGN(MyStateMachine)
    QML_ADDED_IN_VERSION(1, 0)
};

そして、次のようにQMLでインスタンス化することができます:

import MyStateMachine 1.0

MyStateMachine {
    id: stateMachine
}

ステートマシンをコンパイルするには、プロジェクトのビルドファイルに以下の行を追加する必要があります:

cmakeを使う場合

find_package(Qt6 REQUIRED COMPONENTS Scxml)
target_link_libraries(mytarget PRIVATE Qt6::Scxml)
qt6_add_statecharts(mytarget
    MyStatemachine.scxml
)

cmakeを使う場合: qmakeを使う場合:

QT += scxml
STATECHARTS = MyStatemachine.scxml

これにより、qmakeはqscxmlcを実行し、MyStatemachine.hとMyStatemachine.cppを生成し、プロジェクトのヘッダーとソースに適切に追加します。デフォルトでは、生成されたファイルはビルド・ディレクトリに保存されます。qmakeQSCXMLC_DIRまたは cmakeOUTPUT_DIRECTORY変数を設定して、別のディレクトリを指定できます。qmakeQSCXMLC_NAMESPACEまたは cmakeNAMESPACE変数を設定すると、ステートマシンのコードを C++ ネームスペースに置くことができます。

ステートマシンをインスタンス化した後、以下のように任意のステートのアクティブ・プロパティに接続できます。例えば、信号機のステートマシンに、信号が赤であることを示す状態(scxmlファイルでは便利なid "red "を持つ)がある場合、次のように書くことができます:

stateMachine->connectToState("red", [](bool active) {
    qDebug() << (active ? "entered" : "exited") << "the red state";
});

とQMLで記述します:

Light {
    id: greenLight
    color: "green"
    visible: stateMachine.green
}

ステートマシンがイベントを発信したときに通知を受けたい場合は、対応するシグナルに接続します。例えば、メディアプレーヤーのステートマシンが、再生が停止したことを示すイベントを送信する場合、次のように記述します:

stateMachine->connectToEvent("playbackStopped", [](const QScxmlEvent &){
    qDebug() << "Stopped!";
});

とQMLで記述します:

import QtScxml

EventConnection {
    stateMachine: stateMachine
    events: ["playbackStopped"]
    onOccurred: console.log("Stopped!")
}

ステートマシンにイベントを送信するのも、同様に簡単です:

stateMachine->submitEvent("tap", QVariantMap({
    { "artist", "Fatboy Slim" },
    { "title", "The Rockafeller Skank" }
}));

これにより、ステートマシン内の_event.dataにマップの内容が格納された "tap "イベントが生成されます。QMLでは

stateMachine.submitEvent("tap", {
    "artist": "Fatboy Slim"
    "title": "The Rockafeller Skank"
})

Note: ステートマシンが正しく動作するためには、QEventLoop 。イベントループは、delay 属性を実装し、ネストされた(または親)ステートマシンからイベントを受信した際に、ステートマシンの処理をスケジュールするために使用されます。QMLアプリケーションやウィジェットアプリケーションでは、常にイベントループが実行されているので、余計なものは必要ありません。その他のアプリケーションでは、イベントループの処理を開始するためにQApplication::run を呼び出す必要があります。

©2024 The Qt Company Ltd. 本書に含まれるドキュメントの著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。