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. engine.rootContext()->setContextProperty is failing to add property

engine.rootContext()->setContextProperty is failing to add property

Scheduled Pinned Locked Moved Solved QML and Qt Quick
18 Posts 7 Posters 3.1k Views
  • 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.
  • J Offline
    J Offline
    jcdelve
    wrote on last edited by
    #1

    Hello, I'm trying to expose some C++ objects to my QML code, and it won't work. The object appears to be unrecognized in qml (it doesn't highlight a different color), and when I try and return engine.rootObjects(), the list is empty. If this is not how it should be working, then please let me know.

    Here is my main.cpp:

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include "updatescreen.h"
    int main(int argc, char *argv[])
    {
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;
    
    UpdateScreen* screen = new UpdateScreen();
    
    const QUrl url(u"qrc:/main.qml"_qs);
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    
    screen->init();
    
    engine.rootContext()->setContextProperty("UpdateScreen", screen);
    
    if (engine.rootObjects().isEmpty()) {
        return -1;
    }
    engine.load(url);
    return app.exec();
    }
    

    My declaration of UpdateScreen.h as a Q_Object:

    class UpdateScreen : public QObject {
    Q_OBJECT
    
    Q_PROPERTY(int foo READ getFoo WRITE setFoo NOTIFY fooChanged)
    public:
    explicit UpdateScreen(QObject *parent = nullptr);
    void init();
    

    And my qml file trying to access the property:

    Connections {
        target: UpdateScreen
        onFooChanged: {
            a.text = UpdateScreen.getFoo();
        }
    }
    

    Please let me know how I can fix this and get it working! Thank you!!

    KroMignonK 1 Reply Last reply
    0
    • D Offline
      D Offline
      DBoosalis
      wrote on last edited by
      #2

      Where are you emitting your signal fooChanged() . Also if using Version 6 of Qt you need to change signature for connections to :

      Connections {
      target: UpdateScreen
      function onFooChanged() {
      a.text = UpdateScreen.getFoo();
      }
      }

      1 Reply Last reply
      0
      • J jcdelve

        Hello, I'm trying to expose some C++ objects to my QML code, and it won't work. The object appears to be unrecognized in qml (it doesn't highlight a different color), and when I try and return engine.rootObjects(), the list is empty. If this is not how it should be working, then please let me know.

        Here is my main.cpp:

        #include <QGuiApplication>
        #include <QQmlApplicationEngine>
        #include <QQmlContext>
        #include "updatescreen.h"
        int main(int argc, char *argv[])
        {
        QGuiApplication app(argc, argv);
        QQmlApplicationEngine engine;
        
        UpdateScreen* screen = new UpdateScreen();
        
        const QUrl url(u"qrc:/main.qml"_qs);
        QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                         &app, [url](QObject *obj, const QUrl &objUrl) {
            if (!obj && url == objUrl)
                QCoreApplication::exit(-1);
        }, Qt::QueuedConnection);
        
        screen->init();
        
        engine.rootContext()->setContextProperty("UpdateScreen", screen);
        
        if (engine.rootObjects().isEmpty()) {
            return -1;
        }
        engine.load(url);
        return app.exec();
        }
        

        My declaration of UpdateScreen.h as a Q_Object:

        class UpdateScreen : public QObject {
        Q_OBJECT
        
        Q_PROPERTY(int foo READ getFoo WRITE setFoo NOTIFY fooChanged)
        public:
        explicit UpdateScreen(QObject *parent = nullptr);
        void init();
        

        And my qml file trying to access the property:

        Connections {
            target: UpdateScreen
            onFooChanged: {
                a.text = UpdateScreen.getFoo();
            }
        }
        

        Please let me know how I can fix this and get it working! Thank you!!

        KroMignonK Offline
        KroMignonK Offline
        KroMignon
        wrote on last edited by
        #3

        @jcdelve to complete @DBoosalis answer, you should also take care about QML naming convention.
        I don't remember where I found this in Qt documentation, or if it is a JavaScript convention, but all type should (must?!?) be UpperCamelCase and all instances and methodes in lowerCamelCase.

        I would suggest you to change your code to:

        engine.rootContext()->setContextProperty("updateScreen", screen);
        

        And

        Connections {
            target: updateScreen
            function onFooChanged() {
                a.text = updateScreen.getFoo() + "";  // to converter int into string
            }
        }
        

        It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

        1 Reply Last reply
        2
        • J Offline
          J Offline
          jcdelve
          wrote on last edited by jcdelve
          #4

          @DBoosalis
          I update it in UpdateScreen.cpp:

          void UpdateScreen::setFoo(int rate)
          {
              foo = rate;
              emit fooChanged();
          }
          

          I made both your changes, but it still doesn't seem to recognize the QT Object and the application returns -1. Since I return -1, it would seem to imply that it's not adding the object correctly in the rootContext? But I'm not sure why...

          1 Reply Last reply
          0
          • dheerendraD Offline
            dheerendraD Offline
            dheerendra
            Qt Champions 2022
            wrote on last edited by
            #5

            Since it is not giving any object undefined error, it means that object is recognized. I don't see any issue with the object. I suspect that setting value is not right sequence. Where are you setting the value of foo variable ? When are you setting it ? May complete example will help here.

            Dheerendra
            @Community Service
            Certified Qt Specialist
            http://www.pthinks.com

            1 Reply Last reply
            1
            • sierdzioS Offline
              sierdzioS Offline
              sierdzio
              Moderators
              wrote on last edited by
              #6

              @jcdelve said in engine.rootContext()->setContextProperty is failing to add property:

              if (engine.rootObjects().isEmpty()) {
              return -1;
              }

              This will not work. This method returns objects instantiated by the engine, using load() method, which you call later. It does not return context properties.

              engine.rootContext()->setContextProperty("UpdateScreen", screen);

              Only QML components should start with upper case. Try with "updateScreen".

              (Z(:^

              1 Reply Last reply
              0
              • J Offline
                J Offline
                jcdelve
                wrote on last edited by jcdelve
                #7

                @dheerendra Right now, I'm just doing it in the init() method that I call in main.cpp. I'm just trying to establish this functionality before actually implementing it how I need it.

                void UpdateScreen::init()
                {
                    setFoo(20);
                }
                

                main.cpp

                screen->init();
                
                engine.rootContext()->setContextProperty("updateScreen", screen);
                if(engine.rootObjects().isEmpty()) {
                        return -1;
                    }
                    engine.load(url);
                    return app.exec();
                

                @sierdzio I made that change following @KroMignon's post but it did not change anything

                1 Reply Last reply
                0
                • GrecKoG Offline
                  GrecKoG Offline
                  GrecKo
                  Qt Champions 2018
                  wrote on last edited by
                  #8

                  @jcdelve said in engine.rootContext()->setContextProperty is failing to add property:

                  if(engine.rootObjects().isEmpty()) {
                  return -1;
                  }

                  remove that.

                  1 Reply Last reply
                  0
                  • J Offline
                    J Offline
                    jcdelve
                    wrote on last edited by
                    #9

                    Yes, I removed it, and the program runs, but the number I'm looking for doesn't get set to 20 like it should

                    1 Reply Last reply
                    0
                    • sierdzioS Offline
                      sierdzioS Offline
                      sierdzio
                      Moderators
                      wrote on last edited by
                      #10

                      You call init() before your QML is loaded. The fooChanged() signal is fired long before your QML slot (Connections) is ready to receive it.

                      Invoke init() after some delay and it will work.

                      (Z(:^

                      1 Reply Last reply
                      1
                      • J Offline
                        J Offline
                        jcdelve
                        wrote on last edited by
                        #11

                        @sierdzio
                        Good catch, that would definitely be part of the problem. However, the object is still not recognized in the qml file. Using QT Creator, the object I know should appear highlighted and italicized, but it's not. And when I try and call the .getFoo() function, it says it's not a function

                        1 Reply Last reply
                        0
                        • JoeCFDJ Online
                          JoeCFDJ Online
                          JoeCFD
                          wrote on last edited by JoeCFD
                          #12

                          @jcdelve said in engine.rootContext()->setContextProperty is failing to add property:

                          Q_PROPERTY

                          public:
                              Q_INVOKABLE int getFoo(); // This will work.
                          
                          1 Reply Last reply
                          1
                          • J Offline
                            J Offline
                            jcdelve
                            wrote on last edited by jcdelve
                            #13

                            @JoeCFD That worked! I didn't realize I needed that for every single property.
                            I will say it still looks weird, because the object still looks like normal text instead of highlighted or whatever, but it works so I'm not complaining. Thank you!

                            JoeCFDJ 1 Reply Last reply
                            0
                            • J jcdelve

                              @JoeCFD That worked! I didn't realize I needed that for every single property.
                              I will say it still looks weird, because the object still looks like normal text instead of highlighted or whatever, but it works so I'm not complaining. Thank you!

                              JoeCFDJ Online
                              JoeCFDJ Online
                              JoeCFD
                              wrote on last edited by
                              #14

                              @jcdelve Q_INVOKABLE means the func is visible in qml. I am learning as well.

                              1 Reply Last reply
                              1
                              • sierdzioS Offline
                                sierdzioS Offline
                                sierdzio
                                Moderators
                                wrote on last edited by
                                #15

                                @KroMignon said in engine.rootContext()->setContextProperty is failing to add property:

                                a.text = updateScreen.getFoo() + ""; // to converter int into string

                                You don't need to make getFoo() invokable! Just call the property instead of a function:

                                a.text = updateScreen.foo 
                                

                                (Z(:^

                                1 Reply Last reply
                                0
                                • GrecKoG Offline
                                  GrecKoG Offline
                                  GrecKo
                                  Qt Champions 2018
                                  wrote on last edited by
                                  #16

                                  Do it declaratively like so:

                                  // ...
                                  Label {
                                      text: UpdateScreen.foo
                                  }
                                  

                                  it will automatically update when the fooChanged signal is emitted.
                                  Doing Q_INVOKABLE int getFoo(); is ugly.

                                  1 Reply Last reply
                                  1
                                  • J Offline
                                    J Offline
                                    jcdelve
                                    wrote on last edited by
                                    #17

                                    Interesting. By all other conventions of coding standards, it's bad practice to have a variable directly accessible like that... Is there a reason QT/QML prefers that over doing an invokable getter?

                                    sierdzioS 1 Reply Last reply
                                    0
                                    • J jcdelve

                                      Interesting. By all other conventions of coding standards, it's bad practice to have a variable directly accessible like that... Is there a reason QT/QML prefers that over doing an invokable getter?

                                      sierdzioS Offline
                                      sierdzioS Offline
                                      sierdzio
                                      Moderators
                                      wrote on last edited by
                                      #18

                                      @jcdelve said in engine.rootContext()->setContextProperty is failing to add property:

                                      Interesting. By all other conventions of coding standards, it's bad practice to have a variable directly accessible like that... Is there a reason QT/QML prefers that over doing an invokable getter?

                                      Please read up on how Q_PROPERTY system works. You are not accessing a variable, you are accessing a property. QML (via Meta Object System) will use the getter / setter you provide in Q_PROPERTY declaration. It will not access the variable directly.

                                      (Z(:^

                                      1 Reply Last reply
                                      2

                                      • Login

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