Pass and modify C++ data from a Custom QML Item



  • I would like to pass "simply" a variable (defined in a C++ class, shared to QML with "rootContext()->setContextProperty()" ) to a QML Button and modify it on the OnClick event.
    The OnClick event of the CustomBtn would increment the c++ variable with 1.

    // -------------- main.qml --------------

    import QtQuick 2.2
    import QtQuick.Controls 1.1
    
    ApplicationWindow {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
        CustomBtn
        {
            id: aCustomBtn
            myQMLVar: MyQMLObject.value;
        }
    
        Button {
            width: 100
            height: 62
    
            text: "+2"
            onClicked:  {
                MyQMLObject.value = MyQMLObject.value+2
            }
    
            anchors.left: aCustomBtn.right
            anchors.top: aCustomBtn.top
        }
    }
    

    // -------------- CustomBtn.qml --------------

    import QtQuick 2.0
    import QtQuick.Controls 1.1
    
    Item {
        width: 100
        height: 62
    
        property var myQMLVar
    
        Button {
            anchors.fill: parent
            text: "+1"
            onClicked: {
                myQMLVar = myQMLVar+1
            }
        }
    }
    

    // -------------- main.cpp --------------

    #include <QApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include "myobject.h"
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
        MyObject anObj;
    
        QQmlApplicationEngine engine;
        engine.rootContext()->setContextProperty("MyQMLObject", &anObj);
        engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
    
        return app.exec();
    }
    

    // -------------- myobject.h --------------

    #ifndef MYOBJECT_H
    #define MYOBJECT_H
    
    #include <QDebug>
    #include <QObject>
    #include <QVariant>
    
    class MyObject : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged)
    
    public:
        explicit MyObject(QObject *parent = 0);
    
        QVariant value() const {
            return m_value;
        }
    
    signals:
        void valueChanged(QVariant arg);
    
    public slots:
        void setValue(QVariant arg) {
            if (m_value != arg) {
                m_value = arg;
                qDebug() << "m_value:" << m_value;
                emit valueChanged(arg);
            }
        }
    
    private:
        QVariant m_value;
    };
    
    #endif // MYOBJECT_H
    

    Create a QtQuick project and include the code above, the "+1" CustomBtn does not increment the C++ variable, when the "+2" normal button increments it.
    Did the "myQMLVar" property is correctly defined in the CustomBtn?

    Is it just impossible to do it this way ?

    Will I have to copy paste the code from the CustomBtn calling directly "MyObject.value" for each different C++ variable that I want to modify this way ?


  • Moderators

    Hi @Fred-Waltzer,
    Binding doesn't work in reverse order i.e updating myQMLVar wont re-evaluate the expression and thus it won't update MyQMLObject.
    One way would be to update MyQMLObject in myQMLVar handler viz. onMyQMLVarChanged but you may get binding loop.
    BTW, Since you have set MyQMLObject as context property it will be directly accessible in CustomBtn too.



  • Thanks for the answer, that was my biggest fear.
    That is exactly what I didn't want to do...
    Copy+Paste QML code for each CustomBtn and which will modify a different C++ variable.

    Didn't they think about factorizing code when they wrote the QML and C++ bindings ?
    If anyone found a solution other than COPY-PASTE, I'll be glad to hear about it.


  • Moderators

    @Fred-Waltzer MyQMLObject will be available in all the QML files of the project. So no need to create different C++ variable.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.