Cannot add model to QML



  • Hello, I cannot add C++ model to QML which runs in QQuickWidget. I get error while running the application. Error is : "qrc:/Gauge.qml:43: ReferenceError: DataModel is not defined". I can see the gauge when the program is run, it is only that the value is not updating the gauge.

    My code is like this:

    //main.cpp
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
        QQmlApplicationEngine* engine = new QQmlApplicationEngine();
        DataModel datamodel;
        engine->rootContext()->setContextProperty("DataModel", &datamodel);
        engine->load(QUrl(QStringLiteral("qrc:/Gauge.qml")));
        if (engine->rootObjects().isEmpty())
            return -1;
        MainWindow w;
        w.show();
        return app.exec();
    
    //mainwindow.cpp
    MainWindow::MainWindow(QWidget *parent) :  QMainWindow(parent), ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        ui->quickWidget->setSource(QUrl(QStringLiteral("qrc:/Gauge.qml")));
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    
    //datamodel.cpp
    #include "datamodel.h"
    #include <iostream>
    #include <QTimer>
    int temp = 0;
    DataModel::DataModel(QObject *parent) : QObject (parent)
    {
        m_num = 10;
        qDebug() << "Creating datamodel constructing...";
        m_timer = new QTimer(this);
        connect(m_timer, SIGNAL(timeout()), this, SLOT(update()));
        m_timer->start(1000);
    }
    
    int DataModel::num() const
    {
        return m_num;
    }
    
    void DataModel::update()
    {
        temp += 5;
        this->setNum(temp);
        qDebug() << "Updating value:" << m_num;
    }
    
    void DataModel::setNum(int num)
    {
        if (m_num == num)
            return;
        qDebug() << "Setting value:" << num;
        m_num = num;
        emit numChanged(m_num);
    }
    
    
    // datamodel.h
    #ifndef DATAMODEL_H
    #define DATAMODEL_H
    
    #include <QObject>
    #include <QTimer>
    #include <QDebug>
    
    class DataModel : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(int num READ num WRITE setNum NOTIFY numChanged)
    
    public:
        explicit DataModel(QObject *parent = nullptr);
    
        int num() const;
    signals:
        void numChanged(int num);
        void operate();
    
    public slots:
        void setNum(int num);
        void update();
    
    private:
        int m_num;
        QTimer* m_timer;
    };
    #endif // DATAMODEL_H
    
    
    //Gauge.qml
      CircularGauge {
          value: DataModel.num
          anchors.centerIn: parent
          }
      }
    

  • Moderators

    Your MainWindow is creating another QML engine which does not have "DataModel" set.



  • @sierdzio . So, how can i fix it. Do I add DataModel in mainwindow.cpp?


  • Moderators

    @milan said in Cannot add model to QML:

    QQmlApplicationEngine* engine = new QQmlApplicationEngine();

    remove the engine since you're not using it anywhere. Or remove MainWindow if you are not using that. I don't know which is true in your case.

    Extract the engine from your ui->quickWidget and add the DataModel there. If you are using QQuickWidget, you can use https://doc.qt.io/qt-5/qquickwidget.html#engine.



  • @sierdzio .Thanks for your answer, it works. The initial value of gauge is set to 10. But the timer I have in my datamodel does not update the gauge value.


  • Moderators

    @milan said in Cannot add model to QML:

    qDebug() << "Setting value:" << num;

    Do you see this message printed?



  • @sierdzio . I see that DataModel object gets destructed after it is constructed.


  • Moderators

    @milan said in Cannot add model to QML:

    @sierdzio . I see that DataModel object gets destructed after it is constructed.

    So make sure it lives long :-)



  • @sierdzio. Yes I did that. Is qmlregistertype better way that setContextProperty I am using now? The C++ model should update the qml. Is it possible to use qmlregistertype in this context?


  • Moderators

    @milan said in Cannot add model to QML:

    @sierdzio. Yes I did that. Is qmlregistertype better way that setContextProperty I am using now? The C++ model should update the qml

    No it is not better, it server a different purpose. It makes the type recognizable (and creatable) in QML. Since you want to use a global data model (I think), then setting the context property is a better way for your use case. Just make sure DataModel object is not destroyed while your UI is alive. You can do it, for example, by declaring it as a member variable of MainWindow class, or by creating an object on heap and assigning MainWindow as parent.



  • @sierdzio. Thanks a lot for your answer.