How to use QScxmlCppDataModel in QScxmlStateMachine?

591 Views Asked by At

In my project , i use C++ , QScxmlCppDataModel , there is always occur a error , "No data-model instantiated" when i start the state machine,

I follow the Qt document says

1、Add data model in scxml file

<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" binding="early" xmlns:qt="http://www.qt.io/2015/02/scxml-ext" datamodel="cplusplus:DataModel:DataModel.h" name="PowerStateMachine" qt:editorversion="4.6.1" initial="nomal">

2、Create a new data model subclass

#include "qscxmlcppdatamodel.h"
#include <QScxmlEvent>

class DataModel :public QScxmlCppDataModel
{
    Q_OBJECT
    Q_SCXML_DATAMODEL

public:
//    DataModel();

    bool isMoreThan50() const;
    bool isLessThan50() const ;

    int m_power;
    QString m_Descript;
    QVariant m_var;


};

3、load and start state machine

    m_stateMachine = QScxmlStateMachine::fromFile(":/powerStateMachine.scxml");
    for(QScxmlError& error:m_stateMachine->parseErrors())
    {
        qDebug()<<error.description();
    }
    m_stateMachine->connectToEvent("powerLoss", this, &MainWindow::onPowerLossEvent);
    m_stateMachine->connectToEvent("pwoerUp", this, &MainWindow::onPowerUpEvent);

    m_stateMachine->connectToState("low", this, &MainWindow::onLowState);
    m_stateMachine->connectToState("nomal", this, &MainWindow::onNomalState);
    m_stateMachine->connectToState("danger", this, &MainWindow::onDangerState);
    m_stateMachine->connectToState("full", this, &MainWindow::onFullState);
    DataModel *dataModel = new DataModel;
    m_stateMachine->setDataModel(dataModel);
    m_stateMachine->init();

    m_stateMachine->start();

error image

but still have a error :"No data-model instantiated",when i start the state machine , anybody know how to fix it ?? thank you

1

There are 1 best solutions below

0
On

Qt's documentation on QScxmlCppDataModel specifically says:

The C++ data model for SCXML ... cannot be used when loading an SCXML file at runtime.

And that is exactly what you are doing, so instead of loading the scxml file at runtime:

m_stateMachine = QScxmlStateMachine::fromFile(":/powerStateMachine.scxml");

Use the compiled statemachine directly:

MyStateMachine statemachine;
MyDataModel datamodel;
statemachine.setDataModel(&datamodel);

In the example above:

1- MyStateMachine is the value you have assigned to the <name> attribute of the scxml element (i.e. scxml file/model).

2- MyDataModel is the name you have given to your c++ data model class (i.e. your class derived from QScxmlCppDataModel)

class MyDataModel : public QScxmlCppDataModel
{
    Q_OBJECT
    Q_SCXML_DATAMODEL
public:
    MyDataModel();
};

Too late an answer, but hope it helps others.