Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Interacting with QML Objects from C++
Qt 6.12 LTS is out! See what's new in the release blog

Interacting with QML Objects from C++

Scheduled Pinned Locked Moved QML and Qt Quick
qml qt signal p
22 Posts 2 Posters 13.2k Views 2 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.
  • K Khachatur

    Hi @p3c0,

    In my C++ class header file:

    private slots:
      void onTestRectClicked(const QString &theValue);
    
    p3c0P Offline
    p3c0P Offline
    p3c0
    Moderators
    wrote on last edited by p3c0
    #4

    @Khachatur So didn't it get invoked ?
    Was the connection successful ? Was that aRect found ?

    157

    K 2 Replies Last reply
    0
    • p3c0P p3c0

      @Khachatur So didn't it get invoked ?
      Was the connection successful ? Was that aRect found ?

      K Offline
      K Offline
      Khachatur
      wrote on last edited by
      #5

      @p3c0

      Yes, it is not invoked. Also, I can't change the properties(color or visibility) of test_rect from C++.

      I have changed onCLicked of test_rect :

              onClicked: {
                  console.log(visible)
                  console.log(color)
                  console.log("CLICKED")
              }
      

      After launching of application, I am clicking on that test_rect rectangle and I get such output:

      qml: true
      qml: #ff0000 // red color
      qml: CLICKED
      

      then I am clicking the button which calls the C++ code defined abow and in slots onColorChanged and onVisibleChanged I get:

      qml: false
      qml: #008000 // green color
      

      but nothing is changed.

      Then I click again to that red rectangle and I get again the same output

      qml: true
      qml: #ff0000 // red color
      qml: CLICKED
      

      I don't understand what I am doing wrong. May be there are some threads in which the UI elements can be changed? And I am changing properties in wrong thread?

      1 Reply Last reply
      0
      • p3c0P p3c0

        @Khachatur So didn't it get invoked ?
        Was the connection successful ? Was that aRect found ?

        K Offline
        K Offline
        Khachatur
        wrote on last edited by
        #6

        @p3c0
        Yes, the aRect is found and the connection is successful. For testing purposes I tired to connect non-existing signal pressed and I got this:
        QObject::connect: No such signal QQuickRectangle_QML_147::pressed(QString) in OperationCreatePoint.cpp:99
        QObject::connect: (sender name: 'test_rect')

        p3c0P 1 Reply Last reply
        0
        • K Khachatur

          @p3c0
          Yes, the aRect is found and the connection is successful. For testing purposes I tired to connect non-existing signal pressed and I got this:
          QObject::connect: No such signal QQuickRectangle_QML_147::pressed(QString) in OperationCreatePoint.cpp:99
          QObject::connect: (sender name: 'test_rect')

          p3c0P Offline
          p3c0P Offline
          p3c0
          Moderators
          wrote on last edited by
          #7

          @Khachatur Just tested your code and found out that if you remove this if condition

          if(aRoot != NULL)
              {
                 ...
          

          it works. Can you confirm ?
          However I'm too not sure why this works if the condition is removed.

          157

          K 1 Reply Last reply
          0
          • p3c0P p3c0

            @Khachatur Just tested your code and found out that if you remove this if condition

            if(aRoot != NULL)
                {
                   ...
            

            it works. Can you confirm ?
            However I'm too not sure why this works if the condition is removed.

            K Offline
            K Offline
            Khachatur
            wrote on last edited by
            #8

            @p3c0

            I have removed that condition and it is still not working...

            Is it possible that rootObjects or findchild return pointer to the copy of original object?

            p3c0P 1 Reply Last reply
            0
            • K Khachatur

              @p3c0

              I have removed that condition and it is still not working...

              Is it possible that rootObjects or findchild return pointer to the copy of original object?

              p3c0P Offline
              p3c0P Offline
              p3c0
              Moderators
              wrote on last edited by
              #9

              @Khachatur No I guess. Because changing property of those objects reflects the changes.
              Try removing the second if condition too.

              157

              K 1 Reply Last reply
              0
              • p3c0P p3c0

                @Khachatur No I guess. Because changing property of those objects reflects the changes.
                Try removing the second if condition too.

                K Offline
                K Offline
                Khachatur
                wrote on last edited by
                #10

                @p3c0

                I am new in qt and qml, therefore sorry... It was my bad... again :(

                The code below is correct when you are loading the main.qml first time in main.cpp and then get pointer to root object.

                QQmlApplicationEngine anEngine;
                anEngine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                QObject *aRoot = anEngine.rootObjects()[0];
                QQuickWindow* aWindow = qobject_cast<QQuickWindow* >(aRoot);
                if (aWindow)
                {
                 aWindow->show();
                }
                

                I have used code above in my operation class to get pointer to root object of main.qml.

                But such approach is incorrect, because it will not return the pointer to the root object of main.qml, but will create new instance of main.qml and will return pointer to the root object of new created.

                To get the root object of already displayed main.qml file I am using:

                    QQmlEngine *anEngine = QQmlEngine::contextForObject(myViewer)->engine();
                    QObject* aRoot = ((QQmlApplicationEngine*)anEngine)->rootObjects()[0];
                

                Where myViewer has C++ class type and is registered as qml type qmlRegisterType<Viewer>("Viewer", 1, 0, "Viewer"); and defined in main.qml.

                Currently, everything is working, I can change properties of qml objects and can recieve signals from qml.

                But, is there another way to get poiner to the root object of main.qml?

                P.S. Thank you for your response

                p3c0P 1 Reply Last reply
                0
                • K Khachatur

                  @p3c0

                  I am new in qt and qml, therefore sorry... It was my bad... again :(

                  The code below is correct when you are loading the main.qml first time in main.cpp and then get pointer to root object.

                  QQmlApplicationEngine anEngine;
                  anEngine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                  QObject *aRoot = anEngine.rootObjects()[0];
                  QQuickWindow* aWindow = qobject_cast<QQuickWindow* >(aRoot);
                  if (aWindow)
                  {
                   aWindow->show();
                  }
                  

                  I have used code above in my operation class to get pointer to root object of main.qml.

                  But such approach is incorrect, because it will not return the pointer to the root object of main.qml, but will create new instance of main.qml and will return pointer to the root object of new created.

                  To get the root object of already displayed main.qml file I am using:

                      QQmlEngine *anEngine = QQmlEngine::contextForObject(myViewer)->engine();
                      QObject* aRoot = ((QQmlApplicationEngine*)anEngine)->rootObjects()[0];
                  

                  Where myViewer has C++ class type and is registered as qml type qmlRegisterType<Viewer>("Viewer", 1, 0, "Viewer"); and defined in main.qml.

                  Currently, everything is working, I can change properties of qml objects and can recieve signals from qml.

                  But, is there another way to get poiner to the root object of main.qml?

                  P.S. Thank you for your response

                  p3c0P Offline
                  p3c0P Offline
                  p3c0
                  Moderators
                  wrote on last edited by
                  #11

                  @Khachatur

                  But such approach is incorrect, because it will not return the pointer to the root object of main.qml, but will create new instance of main.qml and will return pointer to the root object of new created.

                  Do you mean there are two instances of main.qml ? Which are they ?

                  157

                  K 1 Reply Last reply
                  0
                  • p3c0P p3c0

                    @Khachatur

                    But such approach is incorrect, because it will not return the pointer to the root object of main.qml, but will create new instance of main.qml and will return pointer to the root object of new created.

                    Do you mean there are two instances of main.qml ? Which are they ?

                    K Offline
                    K Offline
                    Khachatur
                    wrote on last edited by
                    #12

                    @p3c0

                    Yes, I mean that there are two instances of main.qml.

                    Doing this you will get the new instance of main.qml:

                    QQmlApplicationEngine anEngine;
                    anEngine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                    QObject *aRoot = anEngine.rootObjects()[0];
                    

                    I didn't get what does it mean "Which are they"?

                    p3c0P 1 Reply Last reply
                    0
                    • K Khachatur

                      @p3c0

                      Yes, I mean that there are two instances of main.qml.

                      Doing this you will get the new instance of main.qml:

                      QQmlApplicationEngine anEngine;
                      anEngine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                      QObject *aRoot = anEngine.rootObjects()[0];
                      

                      I didn't get what does it mean "Which are they"?

                      p3c0P Offline
                      p3c0P Offline
                      p3c0
                      Moderators
                      wrote on last edited by
                      #13

                      @Khachatur How did you check whether they are 2 separate instance ?

                      157

                      K 1 Reply Last reply
                      0
                      • p3c0P p3c0

                        @Khachatur How did you check whether they are 2 separate instance ?

                        K Offline
                        K Offline
                        Khachatur
                        wrote on last edited by
                        #14

                        @p3c0

                        I don't know the way how to check directly whether they are 2 separate instances, but I was relying on logic.

                        In QML slots onColorChanged and onVisibleChanged of test_rect I am printing the 'color' and 'visible' values.

                                onColorChanged: {
                                    console.log(color)
                                }
                        
                                onVisibleChanged: {
                                    console.log(visible)
                                }
                        

                        When I am changing property of QML objects from C++ code:

                                  aRect->setProperty("color", "green");
                                  aRect->setVisible(false);
                        

                        In output console I get the correct values of color and visibility (green and false respectively), but rectangle still remains red and visible.

                        Therefore I make decision that I am working with another instance of main.qml and I was right.

                        p3c0P 1 Reply Last reply
                        0
                        • K Khachatur

                          @p3c0

                          I don't know the way how to check directly whether they are 2 separate instances, but I was relying on logic.

                          In QML slots onColorChanged and onVisibleChanged of test_rect I am printing the 'color' and 'visible' values.

                                  onColorChanged: {
                                      console.log(color)
                                  }
                          
                                  onVisibleChanged: {
                                      console.log(visible)
                                  }
                          

                          When I am changing property of QML objects from C++ code:

                                    aRect->setProperty("color", "green");
                                    aRect->setVisible(false);
                          

                          In output console I get the correct values of color and visibility (green and false respectively), but rectangle still remains red and visible.

                          Therefore I make decision that I am working with another instance of main.qml and I was right.

                          p3c0P Offline
                          p3c0P Offline
                          p3c0
                          Moderators
                          wrote on last edited by p3c0
                          #15

                          @Khachatur No they are exactly the same objects.
                          Consider the following example:
                          main.qml

                          import QtQuick 2.4
                          import QtQuick.Window 2.2
                          
                          Window {
                              visible: true
                              width: 150
                              height: 150
                          
                              Rectangle {
                                  anchors.fill: parent
                              }
                          
                              Component.onCompleted: console.log("From QML: ",this) // prints the root object
                          }
                          

                          your main.cpp

                          QQmlApplicationEngine anEngine;
                          anEngine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                          
                          QObject *aRoot = anEngine.rootObjects()[0];
                          qDebug() << "From C++: " << aRoot;
                          

                          After running if you look at the outputs you can see the same address on both sides which indicates it is the same object.
                          I think there is some other problem in your code.
                          Can you post or upload an updated complete minimal working example which will show the problem ?

                          157

                          K 2 Replies Last reply
                          0
                          • p3c0P p3c0

                            @Khachatur No they are exactly the same objects.
                            Consider the following example:
                            main.qml

                            import QtQuick 2.4
                            import QtQuick.Window 2.2
                            
                            Window {
                                visible: true
                                width: 150
                                height: 150
                            
                                Rectangle {
                                    anchors.fill: parent
                                }
                            
                                Component.onCompleted: console.log("From QML: ",this) // prints the root object
                            }
                            

                            your main.cpp

                            QQmlApplicationEngine anEngine;
                            anEngine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                            
                            QObject *aRoot = anEngine.rootObjects()[0];
                            qDebug() << "From C++: " << aRoot;
                            

                            After running if you look at the outputs you can see the same address on both sides which indicates it is the same object.
                            I think there is some other problem in your code.
                            Can you post or upload an updated complete minimal working example which will show the problem ?

                            K Offline
                            K Offline
                            Khachatur
                            wrote on last edited by
                            #16

                            @p3c0

                            I have checked.

                            This code I am using at the first time in file main.cpp when I am launching the application

                            QQmlApplicationEngine anEngine;
                            anEngine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                            
                            QObject *aRoot = anEngine.rootObjects()[0];
                            qDebug() << "From C++: " << aRoot;
                            

                            Then I am using the same code in my OperationCreatePoint.cpp class and I get the different address of aRoot.

                            The output is:
                            From main.cpp: ApplicationWindow_QMLTYPE_57_QML_74(0x4711600)
                            From OperationCreatePoint.cpp: ApplicationWindow_QMLTYPE_143_QML_160(0x8478fc0)

                            p3c0P 1 Reply Last reply
                            0
                            • K Khachatur

                              @p3c0

                              I have checked.

                              This code I am using at the first time in file main.cpp when I am launching the application

                              QQmlApplicationEngine anEngine;
                              anEngine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                              
                              QObject *aRoot = anEngine.rootObjects()[0];
                              qDebug() << "From C++: " << aRoot;
                              

                              Then I am using the same code in my OperationCreatePoint.cpp class and I get the different address of aRoot.

                              The output is:
                              From main.cpp: ApplicationWindow_QMLTYPE_57_QML_74(0x4711600)
                              From OperationCreatePoint.cpp: ApplicationWindow_QMLTYPE_143_QML_160(0x8478fc0)

                              p3c0P Offline
                              p3c0P Offline
                              p3c0
                              Moderators
                              wrote on last edited by p3c0
                              #17

                              @Khachatur Some confusion. Do you mean you load main.qml twice ? One is main.cpp and another in OperationCreatePoint.cpp ?
                              Atleast from the output it seems.

                              157

                              1 Reply Last reply
                              0
                              • p3c0P p3c0

                                @Khachatur No they are exactly the same objects.
                                Consider the following example:
                                main.qml

                                import QtQuick 2.4
                                import QtQuick.Window 2.2
                                
                                Window {
                                    visible: true
                                    width: 150
                                    height: 150
                                
                                    Rectangle {
                                        anchors.fill: parent
                                    }
                                
                                    Component.onCompleted: console.log("From QML: ",this) // prints the root object
                                }
                                

                                your main.cpp

                                QQmlApplicationEngine anEngine;
                                anEngine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                                
                                QObject *aRoot = anEngine.rootObjects()[0];
                                qDebug() << "From C++: " << aRoot;
                                

                                After running if you look at the outputs you can see the same address on both sides which indicates it is the same object.
                                I think there is some other problem in your code.
                                Can you post or upload an updated complete minimal working example which will show the problem ?

                                K Offline
                                K Offline
                                Khachatur
                                wrote on last edited by
                                #18

                                @p3c0

                                English is not my native language, may be you misunderstood me... Anyway thank you for your response and sorry for misunderstood

                                p3c0P 1 Reply Last reply
                                0
                                • K Khachatur

                                  @p3c0

                                  English is not my native language, may be you misunderstood me... Anyway thank you for your response and sorry for misunderstood

                                  p3c0P Offline
                                  p3c0P Offline
                                  p3c0
                                  Moderators
                                  wrote on last edited by
                                  #19

                                  @Khachatur That's fine :)
                                  If you still have the problem you can post the updated complete minimal working example so that it would be more helpful in finding the problem.

                                  157

                                  K 1 Reply Last reply
                                  0
                                  • p3c0P p3c0

                                    @Khachatur That's fine :)
                                    If you still have the problem you can post the updated complete minimal working example so that it would be more helpful in finding the problem.

                                    K Offline
                                    K Offline
                                    Khachatur
                                    wrote on last edited by
                                    #20

                                    @p3c0

                                    Yes, I meant I was loading main.qml twice in main.cpp and OperationCreatePoint.cpp. Currently, I have not any problem, Thanks :)

                                    I just have another question about QML FileDialog component, but I guess... should I create new thread?

                                    I am using the FileDialog to load and save files. When I am saving file I want to pass to my FileDialog the default file name, but unfortunately FileDialog have not such property, only fileUrl property which is ReadOnly. I don't want to implement my own file dialog component...

                                    p3c0P 1 Reply Last reply
                                    0
                                    • K Khachatur

                                      @p3c0

                                      Yes, I meant I was loading main.qml twice in main.cpp and OperationCreatePoint.cpp. Currently, I have not any problem, Thanks :)

                                      I just have another question about QML FileDialog component, but I guess... should I create new thread?

                                      I am using the FileDialog to load and save files. When I am saving file I want to pass to my FileDialog the default file name, but unfortunately FileDialog have not such property, only fileUrl property which is ReadOnly. I don't want to implement my own file dialog component...

                                      p3c0P Offline
                                      p3c0P Offline
                                      p3c0
                                      Moderators
                                      wrote on last edited by
                                      #21

                                      @Khachatur AFAIK it is still not implemented. Taking this into consideration some one has already implemented their own. See here.

                                      157

                                      K 1 Reply Last reply
                                      0
                                      • p3c0P p3c0

                                        @Khachatur AFAIK it is still not implemented. Taking this into consideration some one has already implemented their own. See here.

                                        K Offline
                                        K Offline
                                        Khachatur
                                        wrote on last edited by
                                        #22

                                        @p3c0

                                        That is exactly what I need. Thank you :)

                                        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
                                        • Unsolved