Referring to an item from a different file



  • I have a file main.qml like this:

    Window {
        visible: true
        width: 500; height: 500
    
        Rectangle {
            id: existingRect
            width: 50; height: 50
            color: "blue";
        }
    }
    

    It's loaded through QQmlApplicationEngine::load. Is there a way to load, at runtime, from C++, the following QML file called newrect.qml:

    Rectangle {
        id: newRect
        width: 10; height: 10
        color: "red";
        parent: existingRect
    }
    

    And have it correctly child to the existingRect defined in main.qml? If I just load it through QQmlApplicationEngine::load, I get a reference error: "existingRect is not defined". Same if I go with:

        QQmlComponent component(&engine);
        component.loadUrl(QUrl("qrc:/newrect.qml"));
        component.create(engine.rootContext());
    

    Any help would be appreciated.


  • Moderators

    Hi!

    Is there a way to load, at runtime, from C++

    Yes. It works like this:

    MyRect.qml

    import QtQuick 2.6
    
    Rectangle {
        width: 10; height: 10
        color: "red";
    }
    

    main.qml

    import QtQuick 2.6
    import QtQuick.Window 2.2
    
    Window {
        visible: true
        width: 600
        height: 400
    
        Rectangle {
            objectName: "existingRect" // sic!
            width: 50; height: 50
            color: "blue";
        }
    }
    

    main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QtQml>
    #include <QQmlComponent>
    #include <QQuickItem>
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        QQmlApplicationEngine engine;
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    
        QQmlComponent component(&engine);
        component.loadUrl( QUrl("qrc:///MyRect.qml") );
    
        QQuickItem *newItem = qobject_cast<QQuickItem *>(component.create());
        QQuickItem *existingItem = engine.rootObjects().at(0)->findChild<QQuickItem*>("existingRect");
        newItem->setParentItem(existingItem);
    
        return app.exec();
    }
    

    Cheers!



  • Hi,

    Thanks, perfect! Well, almost, because I'll have to set the objectName property on all the relevant items, but that's fine. I think.

    But this got me thinking - does it mean I won't be able to interact with the existing objects from the new one? Imagine MyRect has a MouseArea and I wanted to change the color of existingRect when MyRect is clicked.

    MyRect.qml

    import QtQuick 2.0
    
    Rectangle {
        id: newRect
        width: 10; height: 10
        color: "red";
    
        MouseArea {
            anchors.fill: parent
            onClicked: {
                // this will work
                parent.parent.color = "#ff0"
    
                // but this won't, even though existingRect is lazily evaluated
                existingRect.color = "#ff0"
            }
        }
    }
    

    I can reference and thus modify a parent in a straight line, but not a sibling or an item in a completely different hierarchy branch. I guess I could expose a method to look for an item by objectName to the QML engine, or is there a better way?


  • Moderators

    You are right, it's kind of a problem. I'd use something like this here:

    import QtQuick 2.6
    
    Rectangle {
        width: 50; height: 50
        color: "red";
    
        property var someRect: null
    
        MouseArea {
            anchors.fill: parent
            onClicked: someRect.color = "plum"
        }
    }
    
    
    import QtQuick 2.6
    import QtQuick.Window 2.2
    
    Window {
        visible: true
        width: 600
        height: 400
    
        Rectangle {
            id: limeRect
            x: 200
            width: 200
            height: 200
            color: "lime"
        }
    
        Rectangle {
            objectName: "existingRect" // sic!
            id: existingRect
            width: 200; height: 200
            color: "blue";
    
            onChildrenChanged: children[0].someRect = limeRect
        }
    }
    

Log in to reply
 

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