Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Solved Finding QML Components from C++

    QML and Qt Quick
    qml qml context c++
    3
    8
    9204
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Xandl
      Xandl last edited by Xandl

      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?

      1 Reply Last reply Reply Quote 0
      • benlau
        benlau Qt Champions 2016 last edited by

        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.

        1 Reply Last reply Reply Quote 0
        • L
          lqsa last edited by lqsa

          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());
          
          1 Reply Last reply Reply Quote 0
          • Xandl
            Xandl last edited by

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

            1 Reply Last reply Reply Quote 0
            • benlau
              benlau Qt Champions 2016 last edited by

              @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");
              }
              
              1 Reply Last reply Reply Quote 1
              • Xandl
                Xandl last edited by Xandl

                @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

                1 Reply Last reply Reply Quote 0
                • benlau
                  benlau Qt Champions 2016 last edited by

                  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".

                  1 Reply Last reply Reply Quote 0
                  • Xandl
                    Xandl last edited by

                    @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.

                    1 Reply Last reply Reply Quote 0
                    • First post
                      Last post