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

Reading value from QML in C++



  • I am trying to read an int value from my QML side on c++ but this value remains 0 and doesn't update on c++ side while console.log() clearly shows me that it increments after each click . What am I doing wrong here?

    .qml file

    FocusScope {
    
            property alias myrecordint: startbutton.recordint
    
            Rectangle {
                id: buttonPaneShadow
                width: bottomColumn.width + 16
                height: parent.height
                anchors.top: parent.top
                anchors.right: parent.right
                color: "white"
    
                Column {
                    anchors {
                        right: parent.right
                        top: parent.top
                        margins: 8
                    }
    
                    id: buttonsColumn
                    anchors.rightMargin: 20
                    anchors.topMargin: 20
                    spacing: 12
    
                    CameraButton {
                        id: startbutton
                        property int recordint:0
                        text: "Record"
                        visible: camera.videoRecorder.recorderStatus == CameraRecorder.LoadedStatus
                        onClicked:
                        {
                            recordint=recordint+1
                            camera.videoRecorder.record()
                            console.log(recordint)
    
                        }
                    }
               }
          }
     }
    

    .cpp file

    QQmlEngine engine;
    QQmlComponent component(&engine, QUrl("qrc:/VideoCaptureControls.qml"));
    QObject *object = component.create();
    qDebug() << "Property value:" << QQmlProperty::read(object, "myrecordint").toInt();
    

  • Moderators

    hi @Raad

    You're actually not supposed to manipulate the Properties this way.
    Take a look at this topic, on how you should do it https://forum.qt.io/topic/72407/connect-qml-signal-with-c-slot

    or this basic example, if you really want to listen directly to signals from your main.cpp:

    //main.qml
    import QtQuick 2.11
    import QtQuick.Window 2.2
    import QtQuick.Controls 2.4
    
    Window {
        visible: true
        width: 640
        height: 640
    
        property int counter: 0
        onCounterChanged: changed(counter)
    
        signal changed(int counter)
    
        Timer{
            running: true
            interval: 1000
            repeat: true
            onTriggered: counter++
        }
    }
    
    //main.cpp
    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    
    #include "QQmlContext"
    #include <QDebug>
    #include "backend.h"
    
    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
        QGuiApplication app(argc, argv);
        QQmlApplicationEngine engine;
    
        const QUrl url(QStringLiteral("qrc:/main.qml"));
        engine.load(url);
    
        QObject *rootItem = engine.rootObjects().first();
    
        Backend b;
        QObject::connect(rootItem, SIGNAL(changed(int)), &b, SLOT(onValueChanged(int)));
    
        return app.exec();
    }
    
    //backend.h
    #ifndef BACKEND_H
    #define BACKEND_H
    
    #include <QObject>
    #include <QDebug>
    
    class Backend : public QObject
    {
        Q_OBJECT
    public:
        explicit Backend(QObject *parent = nullptr): QObject(parent) {}
    
    signals:
    
    public slots:
        void onValueChanged(int value){qDebug() << value;}
    };
    
    #endif // BACKEND_H
    
    

  • Moderators

    hi @Raad

    You're actually not supposed to manipulate the Properties this way.
    Take a look at this topic, on how you should do it https://forum.qt.io/topic/72407/connect-qml-signal-with-c-slot

    or this basic example, if you really want to listen directly to signals from your main.cpp:

    //main.qml
    import QtQuick 2.11
    import QtQuick.Window 2.2
    import QtQuick.Controls 2.4
    
    Window {
        visible: true
        width: 640
        height: 640
    
        property int counter: 0
        onCounterChanged: changed(counter)
    
        signal changed(int counter)
    
        Timer{
            running: true
            interval: 1000
            repeat: true
            onTriggered: counter++
        }
    }
    
    //main.cpp
    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    
    #include "QQmlContext"
    #include <QDebug>
    #include "backend.h"
    
    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
        QGuiApplication app(argc, argv);
        QQmlApplicationEngine engine;
    
        const QUrl url(QStringLiteral("qrc:/main.qml"));
        engine.load(url);
    
        QObject *rootItem = engine.rootObjects().first();
    
        Backend b;
        QObject::connect(rootItem, SIGNAL(changed(int)), &b, SLOT(onValueChanged(int)));
    
        return app.exec();
    }
    
    //backend.h
    #ifndef BACKEND_H
    #define BACKEND_H
    
    #include <QObject>
    #include <QDebug>
    
    class Backend : public QObject
    {
        Q_OBJECT
    public:
        explicit Backend(QObject *parent = nullptr): QObject(parent) {}
    
    signals:
    
    public slots:
        void onValueChanged(int value){qDebug() << value;}
    };
    
    #endif // BACKEND_H
    
    


  • @J-Hilk Thank you so much for your answer, link and example! but in this case I'm not trying to connect signal and slots between QML and c++. just need to pass the most recent value of QML object to c++. If I'm wrong please correct me because I don't know much about QML :)


  • Moderators

    @Raad

    just need to pass the most recent value of QML object to c++

    But that's what signal and slots are for. To pass data from one object to an other, (void if it's just a signal without data 😉 )

    Currently this, from your opening post:

    QQmlEngine engine;
    QQmlComponent component(&engine, QUrl("qrc:/VideoCaptureControls.qml"));
    QObject *object = component.create();
    qDebug() << "Property value:" << QQmlProperty::read(object, "myrecordint").toInt();
    

    only reads the property once, just after creation. You'll have to regularly call QQmlProperty::read(object, "myrecordint").toInt(); if you want new data without signals

    via a QTimer for example



  • @J-Hilk Thank you so much for your detailed response! now it is all clear to me!!!


Log in to reply