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.
-
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?
-
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 } }