Finding QML Components from C++
-
Hello everyone,
i am trying to find an QML Item from C++ and followed this post as well as the documentation:
http://doc.qt.io/qt-5/qtqml-cppintegration-interactqmlfromcpp.html
Instead of QQmlApplicationEngine i am using QQmlEngine.
Since the documentation states that "Each QML component is instantiated in a QQmlContext. ... In this case, the Text item will be created in the engine's root context.", i create()'d a QQmlComponent with my QQmlEngine given as both, engine and parent in the constuctur, resulting in the created component beeing no were to be found. All of my QQmlEngine's contexts are empty. Yet the console prints that the Component completed successfully.main.cpp
#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlEngine> #include <QQmlContext> #include <QQmlComponent> #include <QDebug> int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlEngine* qmlEngine = new QQmlEngine(0); QQmlComponent* myComponent = new QQmlComponent(qmlEngine, qmlEngine); myComponent->loadUrl( QUrl( QStringLiteral("qrc:/main.qml"))); QObject* myComponentObj = myComponent->create(); if (myComponentObj == 0 || myComponent->isError()) { qDebug() << "Error loading main" << myComponent->errorString(); } // The docu says new QML Compnontents are created in the QQmlEngine's root context qDebug() << "RootContext-Children: " << qmlEngine->rootContext()->children(); // resulting in empty list = "()" qDebug() << "ContextForObjectContext-Children" << QQmlEngine::contextForObject(myComponentObj)->children(); // actual task: QObject *qmlObject = qmlEngine->rootContext()->findChild<QObject*>("myObjectYo"); if (qmlObject == 0) { qDebug() << "'myObjectYo' NOT FOUND."; // main problem. } else { qDebug() << "yay!"; } return app.exec(); }
main.qml
import QtQuick 2.5 Item { objectName: "myObjectYo" Component.onCompleted: console.log("'" + objectName + "' created!") }
console output
QML debugging is enabled. Only use this in a safe environment. qml: 'myObjectYo' created! RootContext-Children: () ContextForObjectContext-Children () 'myObjectYo' NOT FOUND.
Any ideas on this?
-
You should search from qmlEngine->rootObjects().first() . Moreover, if you need to search for root object, you need to do a comparison by yourself before running findChild. findChild search child but not include the parent object.
-
-
@benlau said:
You should search from qmlEngine->rootObjects().first() . Moreover, if you need to search for root object, you need to do a comparison by yourself before running findChild. findChild search child but not include the parent object.
Yet the component is a child, so it should be poping up when im asking it's parent, the qmlEngine, for it's children, no?
Or is the QObject* parent parameter just for fun here?@lqsa said:
You must to set the parent item on a view:
QQuickView *quickView = new QQuickView(qmlEngine, nullptr); quickView->setSource(QUrl(mainView)); QQuickItem *item = qobject_cast<QQuickItem*>(myComponentObj); item->setParentItem(quickView->rootObject());
Have you read the example code?
-
@Xandl said:
@benlau said:
You should search from qmlEngine->rootObjects().first() . Moreover, if you need to search for root object, you need to do a comparison by yourself before running findChild. findChild search child but not include the parent object.
Yet the component is a child, so it should be poping up when im asking it's parent, the qmlEngine, for it's children, no?
Or is the QObject* parent parameter just for fun here?Don't understand which QObject* parameter you mean.
In your example code, myObjectYo is the root object. Therefore, qmlEngine->rootObjects().first() should be equal to myObjectYo. So if you want to find any component from QQmlEngine. You should use this code
QObject *qmlObject = 0; if ( qmlEngine->rootObjects().first()->objectName() == "myObjectYo") { qmlObject = qmlEngine->rootObjects().first(); } else { qmlObject = qmlEngine->rootObjects().first()->findChild<QQobject*>("myObjectYo"); }
-
@benlau said:
Don't understand which QObject* parameter you mean.
QQmlComponent(QQmlEngine * engine, QObject * parent = 0)
@benlau said:
In your example code, myObjectYo is the root object. Therefore, qmlEngine->rootObjects().first() should be equal to myObjectYo. So if you want to find any component from QQmlEngine. You should use this code
Yet the documentation of QQmlComponent::create states that
QQmlComponent(QQmlEngine * engine, QObject * parent = 0)
...
If context is 0 (the default), it will create the instance in the engine' s root context.
...Link QQmlComponent::create
Edit: btw, "rootObjects()" is not a member of QQmlEngine -
I read it wrong. I just thought you are using QQmlApplicationEngine.
Basically , context will not be the parent of created object. It define the scope of the created object like what it could access. In your case, myComponentObj should be "myObjectYo".
-
@benlau said:
I read it wrong. I just thought you are using QQmlApplicationEngine.
Basically , context will not be the parent of created object. It define the scope of the created object like what it could access. In your case, myComponentObj should be "myObjectYo".
Ok, then thank you for your affords :)
The goal of this experiment was to regain pointers to created objects via the QQmlEngine, because i don't have control over their creation, yet it looks like QQmlEngine alone is not capable of that.
So i'll close this thread and go on with QQmlApplicationEngine.
Thank you again.