Instanciación de máquinas de estado

Tanto las máquinas de estado creadas dinámicamente como las compiladas se comportan de la misma manera, tienen las mismas propiedades, estados, modelo de datos, etcétera. Sólo se diferencian en la forma de instanciarlas. Para crear dinámicamente una en C++ a partir de un archivo SCXML, puede utilizar:

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

O, en QML:

import QtScxml

Item {
    property StateMachine stateMachine: scxmlLoader.stateMachine

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

Una máquina de estados compilada puede instanciarse del mismo modo que cualquier objeto C++:

auto *stateMachine = new MyStatemachine;

O:

MyStatemachine stateMachine;

Para utilizar una máquina de estados compilada en QML, puede registrarla como un tipo QML:

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

Luego puedes instanciarla en QML, así:

import MyStateMachine 1.0

MyStateMachine {
    id: stateMachine
}

Para compilar una máquina de estados, hay que añadir las siguientes líneas al archivo de compilación del proyecto:

Cuando se utiliza cmake:

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

Cuando se utiliza qmake:

QT += scxml
STATECHARTS = MyStatemachine.scxml

Esto le dirá a qmake que ejecute qscxmlc que genera MyStatemachine.h y MyStatemachine.cpp, y los añade apropiadamente a las cabeceras y fuentes del proyecto. Por defecto, los archivos generados se guardan en el directorio de construcción. La variable qmake QSCXMLC_DIR o cmake OUTPUT_DIRECTORY puede establecerse para especificar otro directorio. La variable qmake QSCXMLC_NAMESPACE o cmake NAMESPACE se puede establecer para poner el código de la máquina de estados en un espacio de nombres C++.

Después de instanciar una máquina de estados, puedes conectarte a la propiedad activa de cualquier estado de la siguiente manera. Por ejemplo, si la máquina de estado para un semáforo tiene un estado que indica que la luz está en rojo (que tiene el id conveniente "rojo" en el archivo scxml), puede escribir:

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

Y en QML

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

Si quieres recibir una notificación cuando una máquina de estado envía un evento, puedes conectarte a la señal correspondiente. Por ejemplo, para una máquina de estado de reproductor multimedia que indica que la reproducción se ha detenido enviando un evento, puedes escribir:

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

Y en QML

import QtScxml

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

Enviar eventos a una máquina de estados es igual de sencillo:

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

Esto generará un evento "tap" con el contenido del mapa disponible en _event.data dentro de la máquina de estados. En QML:

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

Nota: Una máquina de estados necesita un QEventLoop para funcionar correctamente. El bucle de eventos se utiliza para implementar el atributo delay para eventos y para programar el procesamiento de una máquina de estado cuando se reciben eventos de máquinas de estado anidadas (o padre). Una aplicación QML o una aplicación widget siempre tendrá un bucle de eventos en ejecución, por lo que no se necesita nada extra. Para otras aplicaciones, QApplication::run tendrá que ser llamado para iniciar el procesamiento del bucle de eventos.

© 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.