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. Issue creating c++ object in qml and passing it to c++ function
Forum Update on Monday, May 27th 2025

Issue creating c++ object in qml and passing it to c++ function

Scheduled Pinned Locked Moved Solved QML and Qt Quick
3 Posts 2 Posters 822 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.
  • R Offline
    R Offline
    rigu10
    wrote on 15 Jun 2018, 08:37 last edited by
    #1

    Hello, this is my situation: i have a c++ class that i register as qml type and instantiate it in qml. Then i pass this through some qml Page where i populate this object; at last i want to bring this object back to c++ world.
    Here is an example: i have this CustomObj

    customobj.h:

    #include <QObject>
    #include <QMetaType>
    
    class CustomObj : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
    public:
        explicit CustomObj(QObject *parent = nullptr);
        CustomObj(const CustomObj &other, QObject *parent = nullptr);
        QString name() const { return m_name; }
        void setName(const QString &newName);
    
    signals:
        void nameChanged();
    
    public slots:
    private:
        QString m_name;
    };
    
    Q_DECLARE_METATYPE(CustomObj)
    

    customobj.cpp:

    CustomObj::CustomObj(QObject *parent) : QObject(parent), m_name("test") {
    }
    
    CustomObj::CustomObj(const CustomObj &other, QObject *parent) : QObject(parent) {
        m_name = other.name();
    }
    
    void CustomObj::setName(const QString &newName) {
        m_name = newName;
    }
    

    it has only one attribute m_name setted in the constructor to show the issue.
    I use a Manager to manage this object. Here is the code:

    manager.h:

    #include <QObject>
    #include <iostream>
    
    #include "customobj.h"
    
    class Manager : public QObject {
    
        Q_OBJECT
    public:
        explicit Manager(QObject *parent = nullptr);
        Q_INVOKABLE void doSomething(const CustomObj &obj);
    
    signals:
    public slots:
    };
    

    manager.cpp:

    Manager::Manager(QObject *parent) : QObject(parent) {
    
    }
    
    void Manager::doSomething(const CustomObj &obj) {
    
        std::cout << obj.name().toStdString() << std::endl;
    }
    

    not much to say here, just a function to show the problem.
    In main.cpp i have registered the two objects:

    qmlRegisterType<Manager> ("Manager", 1, 0, "Manager");
    qmlRegisterType<CustomObj> ("CustomObj", 1, 0, "CustomObj");
    

    In main.qml i create the manager and start a stackview:

    ApplicationWindow {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
        Manager {
            id: myManager
        }
    
        StackView {
            id: stackView
    
            anchors.fill: parent
            initialItem: FirstView { }
        }
    }
    

    In FirstView.qml i create the custom object and set the name attribute as user input:

    Page {
        id: root
    
        TextField {
            id: myText
    
            anchors.centerIn: parent
        }
    
        CustomObj {
            id: myCustomObj
    
            name: myText.text
        }
    
        Button {
            id: nextButton
    
            anchors {
                top: myText.bottom
                horizontalCenter: parent.horizontalCenter
                margins: 20
            }
    
            text: "Next"
            onClicked: {
                console.log(myCustomObj.name)
                root.StackView.view.push("qrc:/SecondView.qml", { myCustomObj: myCustomObj })
            }
        }
    }
    

    the output here is obviously correct and show what i have inserted
    Here is the SecondView.qml:

    Page {
        id: root
    
        property CustomObj myCustomObj
    
        Button {
            id: doSomethingButton
    
            anchors.centerIn: parent
            text: "Do something"
            onClicked: {
                console.log(myCustomObj.name)
                myManager.doSomething(myCustomObj)
            }
        }
    }
    

    The output is correct again, but the doSomethingFunction() won't print what i have inserted in TextField, but only "test". Using debugger i have noticed that once i pass myCustomObj to doSomething() method, a new CustomObj is created instead of using the existent one. Any suggestion about this behaviour?
    I have found another way to do the same, but i would still understend why this happends.
    Thanks!

    R 1 Reply Last reply 15 Jun 2018, 10:49
    0
    • R rigu10
      15 Jun 2018, 08:37

      Hello, this is my situation: i have a c++ class that i register as qml type and instantiate it in qml. Then i pass this through some qml Page where i populate this object; at last i want to bring this object back to c++ world.
      Here is an example: i have this CustomObj

      customobj.h:

      #include <QObject>
      #include <QMetaType>
      
      class CustomObj : public QObject
      {
          Q_OBJECT
          Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
      public:
          explicit CustomObj(QObject *parent = nullptr);
          CustomObj(const CustomObj &other, QObject *parent = nullptr);
          QString name() const { return m_name; }
          void setName(const QString &newName);
      
      signals:
          void nameChanged();
      
      public slots:
      private:
          QString m_name;
      };
      
      Q_DECLARE_METATYPE(CustomObj)
      

      customobj.cpp:

      CustomObj::CustomObj(QObject *parent) : QObject(parent), m_name("test") {
      }
      
      CustomObj::CustomObj(const CustomObj &other, QObject *parent) : QObject(parent) {
          m_name = other.name();
      }
      
      void CustomObj::setName(const QString &newName) {
          m_name = newName;
      }
      

      it has only one attribute m_name setted in the constructor to show the issue.
      I use a Manager to manage this object. Here is the code:

      manager.h:

      #include <QObject>
      #include <iostream>
      
      #include "customobj.h"
      
      class Manager : public QObject {
      
          Q_OBJECT
      public:
          explicit Manager(QObject *parent = nullptr);
          Q_INVOKABLE void doSomething(const CustomObj &obj);
      
      signals:
      public slots:
      };
      

      manager.cpp:

      Manager::Manager(QObject *parent) : QObject(parent) {
      
      }
      
      void Manager::doSomething(const CustomObj &obj) {
      
          std::cout << obj.name().toStdString() << std::endl;
      }
      

      not much to say here, just a function to show the problem.
      In main.cpp i have registered the two objects:

      qmlRegisterType<Manager> ("Manager", 1, 0, "Manager");
      qmlRegisterType<CustomObj> ("CustomObj", 1, 0, "CustomObj");
      

      In main.qml i create the manager and start a stackview:

      ApplicationWindow {
          visible: true
          width: 640
          height: 480
          title: qsTr("Hello World")
      
          Manager {
              id: myManager
          }
      
          StackView {
              id: stackView
      
              anchors.fill: parent
              initialItem: FirstView { }
          }
      }
      

      In FirstView.qml i create the custom object and set the name attribute as user input:

      Page {
          id: root
      
          TextField {
              id: myText
      
              anchors.centerIn: parent
          }
      
          CustomObj {
              id: myCustomObj
      
              name: myText.text
          }
      
          Button {
              id: nextButton
      
              anchors {
                  top: myText.bottom
                  horizontalCenter: parent.horizontalCenter
                  margins: 20
              }
      
              text: "Next"
              onClicked: {
                  console.log(myCustomObj.name)
                  root.StackView.view.push("qrc:/SecondView.qml", { myCustomObj: myCustomObj })
              }
          }
      }
      

      the output here is obviously correct and show what i have inserted
      Here is the SecondView.qml:

      Page {
          id: root
      
          property CustomObj myCustomObj
      
          Button {
              id: doSomethingButton
      
              anchors.centerIn: parent
              text: "Do something"
              onClicked: {
                  console.log(myCustomObj.name)
                  myManager.doSomething(myCustomObj)
              }
          }
      }
      

      The output is correct again, but the doSomethingFunction() won't print what i have inserted in TextField, but only "test". Using debugger i have noticed that once i pass myCustomObj to doSomething() method, a new CustomObj is created instead of using the existent one. Any suggestion about this behaviour?
      I have found another way to do the same, but i would still understend why this happends.
      Thanks!

      R Offline
      R Offline
      raven-worx
      Moderators
      wrote on 15 Jun 2018, 10:49 last edited by
      #2

      @rigu10 said in Issue creating c++ object in qml and passing it to c++ function:

      Q_INVOKABLE void doSomething(const CustomObj &obj);

      first thing i noticed is that the signature of your doSomething() method is incorrect.
      It should rather take a QObject* parameter. This instance you can then cast to your custom type:

      void Manager::doSomething(QObject* obj) {
          if( CustomObj* c = qobject_cast<CustomObj*>(obj) )
                qDebug() << c->name();
      }
      

      --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
      If you have a question please use the forum so others can benefit from the solution in the future

      R 1 Reply Last reply 15 Jun 2018, 12:24
      6
      • R raven-worx
        15 Jun 2018, 10:49

        @rigu10 said in Issue creating c++ object in qml and passing it to c++ function:

        Q_INVOKABLE void doSomething(const CustomObj &obj);

        first thing i noticed is that the signature of your doSomething() method is incorrect.
        It should rather take a QObject* parameter. This instance you can then cast to your custom type:

        void Manager::doSomething(QObject* obj) {
            if( CustomObj* c = qobject_cast<CustomObj*>(obj) )
                  qDebug() << c->name();
        }
        
        R Offline
        R Offline
        rigu10
        wrote on 15 Jun 2018, 12:24 last edited by
        #3

        @raven-worx Thanks, this solved my problem :)

        1 Reply Last reply
        1

        1/3

        15 Jun 2018, 08:37

        • Login

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