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

    http://stackoverflow.com/questions/23177839/how-can-i-access-my-window-object-properties-from-c-while-using-qqmlapplicatio

    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?


  • Qt Champions 2016

    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.



  • 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());
    


  • @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?


  • Qt Champions 2016

    @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


  • Qt Champions 2016

    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.


Log in to reply
 

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