Custom QQuickItem : access in C++



  • Hello
    I realize there is an wonderful doc about accessing QML elements from C++ in Qt
    http://doc.qt.io/qt-5/qtqml-cppintegration-interactqmlfromcpp.html#accessing-loaded-qml-objects-by-object-name

    But I have a different problem.
    I am extending QAbstractListModel and within one of the type of items that I use in the models, I sometimes, instantiate a custom QML QuickItem.
    So, this QML item (which has a custom C++ class object in runtime) is directly associated with the model item at a certain index. I can "communicate" with the model item through some Q_PROPERTY binding signals, that change properties in QML, and then BACK to the model item through some roles. But this is SO overkill and heavy, it would be MUCH better if I didn't meddle with QML and emiited some signals directly between C++ objects.

    So, I was wondering how I could access this custom class object within the model item in C++. That way, I could make some connects, and emit some signals, without QML interfering between.

    Thank you



  • Hi @BuzzLEitinho ,
    I would say that this highly depends on your implementation.

    is your custom QML QuickItem initated purly on the QML-Side, or do you have an existing Object in your main.cpp ?

    If you have, than you can do normal connects between existing classes inside the main.cpp. But, because main.cpp is not derived from QObject you'll have to reference it directly:

    //main.cpp
    {
    
    myClass1 mC1;
    myClass2 mC2;
    
    QObject::connect(&mC1, &myClass1::mySignal, &mC2, & myClass2::mySlot);
    

    if not, you should be able to connecct them directly inside QMl as well, the most minimal way I guess.

    Connections{
        target: myCppBackend1
    
        onSignal:myCppBackend2.mySlot(value)
    }
    


  • It is initiated purely on QML-Side, because it is used as a Loader source item, which in turn is inside a repeater with another custom classed derived from QAbstractListModel as the repeater model.

    About the second solution, two points:
    1- How do I access the cpp target?
    2- It is still not ideal. The perfect solution would be a direct connection without QML. Like so:

    QObject::connect(&modelItem, SIGNAL(messageReady), &customQQuickItem, SLOT(onMessageReady));
    

    I obviously have access to the model item, anytime, because I have access to the model (the custom derived QAbstractListModel class). But the problem here is customQQuickItem. I know it exists, because if I place a breakpoint in the constructor, or in the setter of a Q_PROPERTY variable, it works properly. The fact that customQQuickItem is used in QML, it builds it under C++. Because I register a type with:
    qmlRegisterType<customQQuickItem>("CustomGeometry", 1, 0, "customQQuickItem");
    And everytime I create a customQQuickItem in QML, it also creates its "brother instance" in c++. The problem, is access, pointer access, to this "brother instance"



  • @BuzzLEitinho

    ok, a somewhat complexer example to the 2nd solution, hopefully.

    assuming 2 localy (in QML) created Items with cpp-part:

    qmlRegisterType<customQQuickItem>("CustomGeometry", 1, 0, "customQQuickItem");
    qmlRegisterType<otherObject>("OtherObject", 1, 0, "otherObject");
    

    than you should be able to connect signal and slots this way:

    #import CustomGeometry 1.0
    #import OtherObject 1.0
    
    CustomGeometry{
        id: obj1
    }
    
    OtherObject{
       id: obj2
    }
    
    Connections{
        target: obj1//The signal emitter
    
       onMySignal: obj2.mySlot(value) // Qml signal catch to the cpp Signal `mySignal(int value)`
    }
    

    if the otherObject is context Property, that makes the connection a bit easier:

    //main.cpp
    otherObject obj2;
    
    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("obj2", &otherObject);
    
    //QML part
    CustomGeometry{
        id: obj1
        onMySignal: obj2.mySlot(value)
    }
    
    //everything else from the other example can be droped, as obj2 is a "global root property"
    


  • Thank you for the effort.

    The problem is that this "otherObject" is not a QQuickItem, and I do not have a way to get it in QML. This "otherObject" is an item of the model itself.
    So there is no point in initializing it in QML, like you did with

    OtherObject{
       id: obj2
    }
    

    http://doc.qt.io/qt-5/model-view-programming.html#creating-new-models

    The ideal would be to get the pointer to the customQQuickItem instance in c++.
    I'm thinking about setting a role and pass "this" in QML to that role.
    That way I can access the instance in C++ side. But I'm not sure it would work... And I don't know how to access the current item in the model being built in QML side.

    Update: I can access the QQuickItem now.
    Though the method is not so covenient. Not something that I've seen, at least.
    In my modelItem, I keep a *customQQuickItem pointer. Set to null in constructor.
    Then, in QML:

    customQQuickItem {
           id:customItem
           Component.onCompleted: {
                customItemRole = customItem 
            }
    }
    

    Then, on the c++ side. The model handles the role, when QML sets it, and it updates the pointer.
    And now, I have access to the custom QQuickItem


Log in to reply
 

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