Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Using Declarative State Machine with Custom C++ QML types



  • Hi,

    I'd like to create a custom QML type in C++ that can contain one or more state machines. My idea is to have the state machine declared on the qml file.

    So far I have created the following type:

    class TestQML : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged)
    public:
        explicit TestQML(QObject *parent = 0);
        QString getName() const;
        void setName(const QString &name);
    signals:
        void nameChanged();
        void Started();
    
    public slots:
        void start();
    
    private:
        QString m_name;
    };
    

    And the following qml file:

    import testbench 1.0
    import QtQml 2.0
    import QtQml.StateMachine 1.0
    
    Test {
        name: "Test 1"
    
        onTestStarted: {
            machine.running = true;
        }
    
        StateMachine {
            id:machine
            initialState: ini
            running: false
            State {
                id: ini
                SignalTransition {
                    targetState: final
                }
            }
            FinalState {
                id: final
            }
            onFinished: base.finish("OK!")
        }
    
    }
    
    
    

    Where base is an object with a finish slot that have been exposed to the engine using

        m_engine = new QQmlEngine(this);
        m_engine->rootContext()->setContextProperty("base",this);
    

    I execute the QML script by using:

            QQmlComponent component(m_engine, url);
            QObject *obj = component.create();
            TestQML *tst = qobject_cast<TestQML*>(obj);
            if (tst) {
                qDebug() << "Teste ID: "            << tst->getName();
                tst->startTest();
            }
            delete obj;
    

    I am getting the following error:

    QQmlComponent: Component is not ready
    

    If I remove the state machine the program works as expected. I isolated the problem to the "import QtQml.StateMachine 1.0" statment - if I remove it the program runs.
    I read all the documentation available on the Declarative State Machine framework but I couldn't find anything related to this particular problem. Does anyone have had similar problems importing the framework? Is there a particular Qt Module that I have to link against in order to have StateMachine working?



  • @GRAlves
    I found that I was missing the qml-module-qtqml-statemachine module on my ubuntu installation. That fixed the crash with the import statement but I still can't get the Test obejct to accept a StateMachine as a part of it. Is there some modification I need to do on the C++ class for it to accept StateMachine children?

    After some more debugging I arrived to the following qml:

    Teste {
        id: teste1
        name: "Teste 1"
    
        onTestStarted: {
            maquina.running = true;
        }
        StateMachine {
                id:maquina
                initialState: inicio
                running: false
                State {
                    id: inicio
                    SignalTransition {
                        targetState: finalizou;
                    }
                }
                FinalState {
                    id: finalizou;
                }
                onFinished: base.finish("Tudo certo!")
            }
    }
    

    It is now failing with

    QQmlComponent: Component is not ready
    (file:///.../teste1.qml:15:5: Cannot assign to non-existent default property
            StateMachine {
            ^)
    

    I am pretty sure I need to add something to the TestQML class in order to make it work but I couldn't find any documentation on how to nest a State Machine on a custom QML type.



  • I couldn't get it to work deriving from QObject. My workaround was to derive TestQML from QQuickItem instead of QObject.


Log in to reply