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

Panes/Ids dont seem to work with objects crated from a C++ context



  • Hello,

    I have a QContextObject which was created by a C++ backend and which I instantiate in qml via Qt.createInstance..
    This all works fine, however there are some strange things I see as inconsistent behaviour.

    1. I can not access other objects ids from these objects. id.parent works fine and i can manipulate objects through this, but ids for other objects dont seem to work.

    2. Furthermore I can not seem to manipulate Pane objects in qml. What I mean by this is that when I have a parent object Item i can set the foucs property via id.parent.focus = .. However, when I make this Item object a Pane, this does not seem to work. Similar things happen for the ObjectName property. It does not return the correct object name for Pane Objects.

    Is there any explanation for these two problems?


  • Moderators

    I don't know about 2. But 1. is correct behaviour. IDs are not visible to C++ code and are only visible to QML code when in scope (in the same file). It's annoying at times, but it is a design decision. You can get around this by:

    • using objectName() and findChildren() to get the objects you want
    • use qml-private module to get the APIs for real IDs. This is discouraged though


  • @sierdzio said in Panes/Ids dont seem to work with objects crated from a C++ context:

    I don't know about 2. But 1. is correct behaviour. IDs are not visible to C++ code and are only visible to QML code when in scope (in the same file). It's annoying at times, but it is a design decision. You can get around this by:

    I see, just to clarify: I am trying to access the ids in qml but the context was created in C++. I am not trying to access ids from C++


  • Moderators

    Oh hm ok, I misunderstood you, then. I'm not sure if my argument holds in such case. Perhaps it is a Qt bug.

    Can you share some code, so we can see what you try to do and how? Maybe that will help.



  • So I crate my context as such:

        auto rootObj = qmlApplicationEngine.rootObjects().first();
        auto child = rootObj->findChild<QObject*>("eRectObj");
        
        auto component =  QSharedPointer<QQmlComponent>(new QQmlComponent(qmlApplicationEngine.rootContext()->engine(), QUrl::fromLocalFile(":/qml/ComponentItem.qml"), QQmlComponent::CompilationMode::PreferSynchronous, child));
        component.data()->setParent(child);
        mItems.append({ QStringLiteral("component 1"), QStringLiteral("ComponentItem.qml"), component });
        mItems.append({ QStringLiteral("component 2"), QStringLiteral("ComponentItem.qml"), component });
    

    Then I create an instance in qml via:

           var component =  componentDisplay.componentObject;
            draggedItem = component.createObject(eRect, {"image": componentDisplay.image, name: componentDisplay.displayName, x: posnInWindow.x, y: posnInWindow.y});
    

    My main.qml looks like this:

     // Pane does not seem to work correctly with C++ integration
                Item {
    
                    id: ePane
                    //focus: true
                    objectName: "ePaneObj"
                    Layout.fillWidth: true
                    Layout.fillHeight: true
                    Layout.preferredHeight: 600
                    Layout.preferredWidth: 600
                    Layout.alignment: Qt.AlignTop
    
                    // When not using a Pane we have to set these margins explicitly
                    Layout.topMargin: 11;
                    Layout.bottomMargin: 11;
    
                    Item {
                        id: eItem
    
                        anchors.fill: parent
                        objectName: "eItemObj"
                        implicitHeight: parent.height
                        implicitWidth: parent.width
                        Rectangle {
                            id: eRect
                            objectName: "eRectObj"
                            implicitWidth: parent.width
                            implicitHeight: parent.height
                            color: "white"
                            border.color: "black"
    
                            MouseArea {
                                id: ePaneMouseArea
                                anchors.fill: parent
                            }
                       }
    
                     }
    
                    Keys.onPressed: {
                        if(event.key === Qt.Key_D) {
                            for(var i = 1; i < eRect.children.length; i++){
                                var child = eRect.children[i];
                                if(child.focus){
                                    child.destroy();
                                }
                            }
                        }
                    }
    
    
                }
    
    

    When I want to access the ids of main.qml via:

         //ePane.focus = true
        // Apparently ids dont work dynamically crated objects from c++ contexts
        componentItem.parent.parent.parent.focus = true;
    

  • Moderators

    So ePane is defined in main.qml? And where do you call that ePane.focus = true, also in main.qml?



  • I call ePane.focus = true in a javascript file associated with the instance I create via component.createObject. Its similar to the drag and drop example from the QT: https://doc.qt.io/archives/qt-4.8/qt-declarative-toys-dynamicscene-example.html

    Except that the object components which the instances are crated form are stored in a c++ ListModel similar to https://www.youtube.com/watch?v=9BcAYDlpuT8 (also a QT example)


  • Moderators

    I see. IDs in separate JS files do work, indeed, as long as the ID comes from the QML file which includes the script.

    I don't think I know how to help, sorry :-( Perhaps it is indeed something about initialization on C++ side, or I still misunderstand what's going on, I don't know.


Log in to reply