Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Finding QML Components from C++
Forum Updated to NodeBB v4.3 + New Features

Finding QML Components from C++

Scheduled Pinned Locked Moved Solved QML and Qt Quick
qmlqml contextc++
8 Posts 3 Posters 10.8k Views 1 Watching
  • 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.
  • XandlX Offline
    XandlX Offline
    Xandl
    wrote on last edited by Xandl
    #1

    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
    0
    • benlauB Offline
      benlauB Offline
      benlau
      Qt Champions 2016
      wrote on last edited by
      #2

      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
      0
      • L Offline
        L Offline
        lqsa
        wrote on last edited by lqsa
        #3

        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
        0
        • XandlX Offline
          XandlX Offline
          Xandl
          wrote on last edited by
          #4

          @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
          0
          • benlauB Offline
            benlauB Offline
            benlau
            Qt Champions 2016
            wrote on last edited by
            #5

            @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
            1
            • XandlX Offline
              XandlX Offline
              Xandl
              wrote on last edited by Xandl
              #6

              @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
              0
              • benlauB Offline
                benlauB Offline
                benlau
                Qt Champions 2016
                wrote on last edited by
                #7

                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
                0
                • XandlX Offline
                  XandlX Offline
                  Xandl
                  wrote on last edited by
                  #8

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

                  • Login

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved