Reference item id in a dynamic loaded file



  • I have a main window, which is defined in main.qml (Not my real code, just a simple example)

    ApplicationWindow {
        width: 800
        height: 480
        visible: true
        id: appWindow
    
        Item {
            clip: true
            id: appContainer
            width: 100
            height: 100
            anchors.centerIn: parent
        }
    }
    

    The item appContainer has a defined size and works as a container for another item which is loaded dynamically via C++

    ...
    QQmlComponent component(getEngine(), QUrl("mychild.qml", QQmlComponent::PreferSynchronous);
    if(component.isLoading() || component.isError()) {
        qDebug() << component.errorString();
        return false;
    }
    QObject *object = component.create(getEngine()->rootContext());
    this->view = qobject_cast<QQuickItem*>(object);
    this->view->setParent(this->parent);
    this->view->setParentItem(this->parent);
    ...
    

    from mychild.qml. The qml file contains a rectangle which should fill the entire Screen

    Rectangle {
        anchors.fill: appContainer
        color:"black"
    }
    

    But the rectangle cant reference to the root container and throws the error "ReferenceError: appContainer is not defined"
    How can i access item ids from other files if some of them are loaded dynamically?

    The reason i ask is because i need to create a message box which should be closed if the user click somewhere outside the box.

    Since i work with an embedded system with EGLFS (No window manager) i can not use the Window or Dialog items which would create a window for me. So i have to create something own with Rectangle and this basic stuff.
    My idea was to put a screen filling rectangle and mousearea under the message box to dark the items in the background for a better optic and to catch the mouseevents outside the box. But therefor i need to get the screen dimensions from the root item in my main.qml file.


  • Moderators

    Hi @PhTe,
    You will need to find that exact Item. It can be done using findChild. An example here. Then set this item as parent item using setParentItem for the newly created component.



  • Hi @p3c0,
    i have already done this. (Look at the last two lines in my C++ example above)
    The items from mychild.qml are shown correctly, as long as they dont refer to an item id from the main.qml.


  • Moderators

    @PhTe I think you are setting a wrong parent item. I would suggest you to set correct parent from C++ by finding it (i.e find appContainer) as said earlier. And then in mychild.qml anchors.fill: parent should work.



  • @p3c0 Oh, i just saw, i made a misstake in my example above, sorry.
    The rectangle in mychild.qml should fill the appWindow, not the appContainer item.

    Here is a complete, compilable example of what i mean:

    main.qml

    import QtQuick 2.4
    import QtQuick.Controls 1.3
    import QtQuick.Window 2.2
    import QtQuick.Dialogs 1.2
    
    ApplicationWindow {
        width: 800
        height: 480
        visible: true
        id: appWindow
    
        Item {
            clip: true
            id: appContainer
            objectName: "appContainer"
            width: 100
            height: 100
            anchors.centerIn: parent
        }
    }
    

    mychild.qml

    import QtQuick 2.0
    
    Item {
        anchors.fill: parent
    
        // Should fill the entire screen ( NOT WORKING - 'appWindow is not defined' )
        Rectangle {
            anchors.fill: appWindow
            color: "black"
        }
    
        // Should fill a 100 x 100 px area ( WORKING )
        Rectangle {
            anchors.fill: parent
            color: "red"
        }
    }
    

    main.cpp

    #include <QApplication>
    #include <QQmlApplicationEngine>
    #include <QQuickItem>
    #include <QQuickWindow>
    
    int main(int argc, char *argv[]) {
        QApplication app(argc, argv);
        QQmlApplicationEngine engine;
    
        // Load main.qml
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    
        // Get top level item
        QList<QObject*> temp = engine.rootObjects();
        QObject *topLevel = temp.value(0);
        QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);
    
        // Find parent for dynamically loaded content
        QQuickItem *appContainer = window->findChild<QQuickItem*>("appContainer");
    
        // Load mychild.qml
        QQmlComponent component(&engine, QUrl("qrc:/mychild.qml"), QQmlComponent::PreferSynchronous);
        if(component.isLoading() || component.isError()) 
            qDebug() << component.errorString();
        QObject *object = component.create(engine.rootContext());
        QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership);
        QQuickItem *view = qobject_cast<QQuickItem*>(object);
    
        // Set parent
        view->setParent(appContainer);
        view->setParentItem(appContainer);
        view->setVisible(true);
    
        window->show();
        return app.exec();
    }
    

    The red rectangle is drawn in the center of the screen but the black rectangle, which should fill the entire screen, is not drawn.

    I have tried to put the code from mychild.qml into main.qml, but then (with some changes) i get an error that an item
    "Cannot anchor to an item that isn't a parent or sibling."
    So i think its not possible in general, to create an item that anchors to some other item then its own parent if the parent isnt self anchored to something.


  • Moderators

    @PhTe Right it wont work. It cannot anchor to an item which is not its parent or sibling.



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