Qt Forum

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

    Qt Academy Launch in California!

    Unsolved Calling function from object of object in QML results in TypeError

    QML and Qt Quick
    2
    8
    1269
    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.
    • P
      prex last edited by

      I'm trying to connect a function of a C++ object of another C++ object to my QML UI. The first C++ object lives in a separate QThread. The structure is as follows:

      • main.qml
      • main.cpp
        • Base class, QThread
          • Hardware class

      Which means that the Hardware class is just an object created in the QThread Base.

      I would like to connect my QML UI to the functions of the Hardware class. So I set the context property:

      Base* base = new Base(argc, argv);
      engine.rootContext()->setContextProperty("base", base);
      

      I was not able to connect to the functions of the Hardware class, e.g.

      onClicked: base.hardware.resetSystem()
      

      fails with

      qrc:/SideBarForm.ui.qml:95: TypeError: Cannot call method 'resetSystem' of undefined
      

      But I can successfully call functions of the base class, e.g.

      onClicked: base.test()
      

      And calling the function from main.cpp works also fine:

      base->hardware->resetSystem();
      

      Furthermore, hardware is public in Base and resetSystem() is a public slot in Hardware:

      public:
        std::shared_ptr<Hardware> hardware;
      

      --

      public slots: 
        void resetSystem();
      

      What is the proper way of connecting signals and slots from "sub-objects" in QThreads to a QML interface?

      ODБOï 1 Reply Last reply Reply Quote 0
      • ODБOï
        ODБOï @prex last edited by ODБOï

        @prex one simple way is to add a Q_INVOKABLE method (or public slot) to Base

        Q_INVOKABLE void resetHardwareSys(){
         hardware->resetSystem();
        }
        

        or you can expose your Hardware to QML adding a Q_PROPERTY for it and returning it as a QVariant (it is not enough to set it public to access it in QML )

        P 1 Reply Last reply Reply Quote 1
        • P
          prex @ODБOï last edited by

          @LeLev Thanks, this works now. So the first solution means going over two public slots. I'm wondering about how to handle signals from C++ to QML then. First using QObject::connect() and then the Connections QML type? I have lots of data from the Hardware class which I need to visualize in the UI.

          I was reading many posts about signals & slots not working between QML and QThreads. I'm a little bit confused since it seems to work here...

          1 Reply Last reply Reply Quote 0
          • P
            prex last edited by

            I like the Q_PROPERTY approach in general but I don't understand what you mean by

            @LeLev said in Calling function from object of object in QML results in TypeError:

            you can expose your Hardware to QML adding a Q_PROPERTY for it and returning it as a QVariant (it is not enough to set it public to access it in QML )

            At the moment I have different Q_PROPERTIES defined in my Hardware class, but how can I make them accessible by QML? Or do you mean adding a Q_PROPERTY for the whole Hardware class?

            ODБOï 1 Reply Last reply Reply Quote 0
            • ODБOï
              ODБOï @prex last edited by ODБOï

              @prex said in Calling function from object of object in QML results in TypeError:

              you mean adding a Q_PROPERTY for the whole Hardware class?

              yes,
              for the getter method, don't return the hardware object directly, use QVariant::fromValue to return it as a QVariant

              P 1 Reply Last reply Reply Quote 0
              • P
                prex @ODБOï last edited by

                @LeLev I‘m not sure if I understand correctly. Should I do something like

                Q_PROPERTIES(Hardware hardware ...)
                

                in Base? But how to access this then? Can you please elaborate a little bit more on it?

                ODБOï 1 Reply Last reply Reply Quote 0
                • ODБOï
                  ODБOï @prex last edited by ODБOï

                  @prex hi

                  class Hardware : public QObject
                  {
                      Q_OBJECT
                  public:
                      explicit Hardware (QObject *parent = nullptr);
                  public slots:
                  
                      void write(const QString &str){
                          qDebug()<< str;
                      }
                  };
                  
                  class Example : public QObject
                  {
                      Q_OBJECT
                      Q_PROPERTY( Hardware * hardware READ hardware NOTIFY hardwareChanged)
                  
                  public:
                      explicit Example(QObject *parent = nullptr);
                  
                      Hardware * hardware (){
                          return  m_hardware;
                      }
                  signals:
                      void hardwareChanged();
                  
                  private:
                      Hardware *m_hardware;
                  };
                  
                   Example e;
                      engine.rootContext()->setContextProperty("obj",&e);
                  
                  import QtQuick 2.12
                  import QtQuick.Window 2.12
                  
                  Window {
                      visible: true
                      width: 640
                      height: 480
                      title: qsTr("Hello World")
                  
                      Component.onCompleted: obj.hardware.write("hello")
                  
                  }
                  
                  
                  P 1 Reply Last reply Reply Quote 1
                  • P
                    prex @ODБOï last edited by

                    @LeLev Thank you very much for the code sample!

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