How to get a valid object instance of a QQuickItem on C++ side



  • Alright. I have searched a lot but haven't got a good solution yet. I am new to Qt. I have a class which is a QQuickItem like so,

    class MyQuickItemClass : public QQuickItem
    {
        Q_OBJECT
        SetInfo(SomeCppClass object)
    };
    

    I do a qmlRegisterType in my main.cpp to register it on the qml side like this,

    qmlRegisterType< MyQuickItemClass >("MyQuickItemClass", 1, 0, "MyQuickItemClass");

    All fine till here. But -> I want to set an object instance & some properties in MyQuickItemClass which some C++ logic in it as well & then pass the MyQuickItemClass object to qml. Or, get a valid instance of MyQuickItemClass from Qml. How can I get a vlid instance MyQuickItemClass object instance from QML on C++ side in main.cpp ?

    I tried doing the following learning from the link here. But this technique creates two separate objects of MyQuickItemClass. One from QML, & one from c++ side. Hence does not work for me.

    Following is how I am trying to do this after lot of searching.

    int main(int argc, char *argv[]) 
    {
      qmlRegisterType< MyQuickItemClass >("MyQuickItemClass", 1, 0, "MyQuickItemClass");
      QQmlApplicationEngine engine;
      SomeCppClass someCppClassObject;
      someCppClassObject.updateSomething();
    
      MyQuickItemClass myquickItemObject;
      myquickItemObject.SetInfo(someCppClassObject);
      engine.rootContext()->setContextProperty("myquickItemObject", &myquickItemObject);
    
      engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
      return app.exec();
    }
    

    But, doing the above gets the constructor of MyQuickItemClass called twice. Once from cpp side when I created an object, and once from qml side. Verified this by placing a breakpoint in the constructor of MyQuickItemClass as well. As a result, someCppClassObject that I had set is null inside MyQuickItemClass when program runs. Because qml has made the final call to MyQuickItemClass to instantiate, thusly ignoring the MyQuickItemClass object that I created in main.cpp.

    Here is my qml´ code forMyQuickItemClass`:

    import QtQuick 2.5
    import MyQuickItemClass 1.0
    
    ParentContainerItem {
      id: parentItem
      color: "black"
    
      MyQuickItemClass {
          id: myQuickItemID
          visible: true
          objectName: "myQuickItem"
    
          property bool someProperty1: false
          property bool someProperty2: true
    
          anchors.top: parent.top
          anchors.horizontalCenter: parent.horizontalCenter
      }
    
      //Other qml components
    }
    

    And this is the C++ class whose object needs to be set into MyQuickItemClass.

    SomeCppClass {
      //Pure C++ class. No Qt
    }
    

    Please note that I need to keep MyQuickItemClass derived from QQuickItem. Please suggest...


  • Moderators

    @Nelson_Piquet Use findChild to find that instantiated QML type from C++ using objectName and cast it to QQuickItem



  • @p3c0 Thanks for your attention on this. Can you pls show some sample code ?


  • Moderators



  • @p3c0 I saw the code in the link you provided.

    QObject *rect = object->findChild<QObject*>("rect");
    if (rect)
         rect->setProperty("color", "red");
    

    Can I pass a pure C++ class object instance into setProperty ?


  • Moderators

    @Nelson_Piquet I guess. Maybe you can try QVariant::fromValue but first Does this solve your original question? I.e getting access of QML object from C++?



  • @p3c0 I read & tried to understand this technique of findChild. Not sure how I can change my main.cpp to include this technique of findchild. Doesnt it require to change the way I am loading my main.qml ? Below is the full code demonstration of how I should do this with findchild. Right ?

    QQuickView view;
    view.setSource(QUrl::fromLocalFile("main.qml"));
    view.show();
    QObject *object = view.rootObject();
    QObject *rect = object->findChild<QObject*>("MyQuickItemClass");
    if (rect)
        rect->setProperty("color", "red");
    

    But Can I set a C++ class object into SetProperty ?

    I looked at some other possibilities: Below is something I have cooked up but YET TO SOLVE THE PROBLEM !!!!

    qmlRegisterType< MyQuickItemClass >("MyQuickItemClass", 1, 0, "MyQuickItemClass");
    QQmlApplicationEngine engine;
    HelloCpp cppObjectOnqmlSide;
    qmlRegisterType<HelloCpp>("HelloCppClass", 1, 0, "HelloCppObj");
    engine.rootContext()->setContextProperty("theCppObject", &cppObjectOnqmlSide);
    engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
    return app.exec();
    

    Now on the QML side, below is what I am doing

    import HelloCppClass 1.0
    
    HelloCppObj {
            id: theCppObject
    }
    
    MyQuickItemClass {
      id: myQuickItemID
      visible: true
      objectName: "myQuickItem"
    
      property bool someProperty1: false
      property bool someProperty2: true
    
      anchors.top: parent.top
      anchors.horizontalCenter: parent.horizontalCenter
    
     Component.onCompleted: {
         print("MyQuickItemClass Component.onCompleted called")
         theCppObject.printMessage("someMessage") //Can I pass MyQuickItemClass object into printMessage ?
      }
    

    }

    My question is : Can I pass MyQuickItemClass object into printMessage ? How should I change printMessage to do that ? If I can, then this should solve my problem


  • Moderators

    @Nelson_Piquet Your original question as seen in the title of this post:

    How to get a valid object instance of a QQuickItem on C++ side

    Yes. Using findChild was the answer.

    Now coming to your second question:

    Can I pass MyQuickItemClass object into printMessage ? How should I change printMessage to do that ? If I can, then this should solve my problem

    Yes. Modify your printMessage function to accept MyQuickItemClass class instance as a paramater. Then when you call the function from QML just pass this to it:

    Component.onCompleted: {
         print("MyQuickItemClass Component.onCompleted called")
         theCppObject.printMessage(this) 
    }
    

    Or if its from outside just pass MyQuickItemClass id i.e myQuickItemID



  • @p3c0 Sorry about swaying from the original question. Thanks a lot for all the information. That helps.


Log in to reply
 

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