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. Calling function from object of object in QML results in TypeError

Calling function from object of object in QML results in TypeError

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
8 Posts 2 Posters 2.6k 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.
  • P Offline
    P Offline
    prex
    wrote on 26 Nov 2019, 12:48 last edited by
    #1

    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?

    O 1 Reply Last reply 26 Nov 2019, 13:11
    0
    • P prex
      26 Nov 2019, 12:48

      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?

      O Offline
      O Offline
      ODБOï
      wrote on 26 Nov 2019, 13:11 last edited by ODБOï
      #2

      @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 26 Nov 2019, 14:08
      1
      • O ODБOï
        26 Nov 2019, 13:11

        @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 Offline
        P Offline
        prex
        wrote on 26 Nov 2019, 14:08 last edited by
        #3

        @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
        0
        • P Offline
          P Offline
          prex
          wrote on 26 Nov 2019, 17:39 last edited by
          #4

          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?

          O 1 Reply Last reply 26 Nov 2019, 18:13
          0
          • P prex
            26 Nov 2019, 17:39

            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?

            O Offline
            O Offline
            ODБOï
            wrote on 26 Nov 2019, 18:13 last edited by ODБOï
            #5

            @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 26 Nov 2019, 18:41
            0
            • O ODБOï
              26 Nov 2019, 18:13

              @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 Offline
              P Offline
              prex
              wrote on 26 Nov 2019, 18:41 last edited by
              #6

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

              O 1 Reply Last reply 27 Nov 2019, 08:44
              0
              • P prex
                26 Nov 2019, 18:41

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

                O Offline
                O Offline
                ODБOï
                wrote on 27 Nov 2019, 08:44 last edited by ODБOï
                #7

                @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 29 Nov 2019, 20:03
                1
                • O ODБOï
                  27 Nov 2019, 08:44

                  @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 Offline
                  P Offline
                  prex
                  wrote on 29 Nov 2019, 20:03 last edited by
                  #8

                  @LeLev Thank you very much for the code sample!

                  1 Reply Last reply
                  0

                  3/8

                  26 Nov 2019, 14:08

                  5 unread
                  • Login

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