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. Registering an Instantiable Object Type
Forum Update on Monday, May 27th 2025

Registering an Instantiable Object Type

Scheduled Pinned Locked Moved Solved QML and Qt Quick
9 Posts 2 Posters 727 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.
  • ODБOïO Offline
    ODБOïO Offline
    ODБOï
    wrote on last edited by
    #1

    Hi,
    Im trying to Register an Instantiable Object just like in this official example
    But when i create the object QML side, my properties are not assigned

    //my class simplified (i keep only one property)
    class PlcCom : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(int port READ port WRITE setPort NOTIFY portChanged)
    
    public:
        explicit PlcCom(QObject *parent = nullptr);
    
        int port() const {  return m_port; }
        void setPort(int port)
        {
            if (m_port == port)
                return;
            m_port = port;
            emit portChanged(m_port);
        }
    //...
    
    private :
    int m_port = 0;
    QString hostAdr = "127.0.0.1";
    ...
    //main.cpp
      qmlRegisterType<PlcCom>("com.not.testComApi", 1, 0, "PlcCom");
    
    //qml
    import com.not.testComApi 1.0
    
    Window {
        PlcCom{
             id:p2
    
             port:62944
    
             hostAdr: "10.81.4.108"
             request : "myRequest"
             Component.onCompleted: {         // i also tryed   
                 //p2.hostAdr = "10.81.4.108"
                 //p2.port = 62944
                 //request =  "myRequest"
             }
         }
    

    the problem is my object is created with default property values, this line in PlcCom ctor

     qDebug()<<"connecting : " << m_hostAdr << ":"<<m_port;
    

    will output :

    connecting : "127.0.0.1" : 0 but i expect 10.81.4.108:62944

    Can someone tell me what i'm missing please ?

    J.HilkJ 1 Reply Last reply
    0
    • ODБOïO ODБOï

      Hi,
      Im trying to Register an Instantiable Object just like in this official example
      But when i create the object QML side, my properties are not assigned

      //my class simplified (i keep only one property)
      class PlcCom : public QObject
      {
          Q_OBJECT
          Q_PROPERTY(int port READ port WRITE setPort NOTIFY portChanged)
      
      public:
          explicit PlcCom(QObject *parent = nullptr);
      
          int port() const {  return m_port; }
          void setPort(int port)
          {
              if (m_port == port)
                  return;
              m_port = port;
              emit portChanged(m_port);
          }
      //...
      
      private :
      int m_port = 0;
      QString hostAdr = "127.0.0.1";
      ...
      //main.cpp
        qmlRegisterType<PlcCom>("com.not.testComApi", 1, 0, "PlcCom");
      
      //qml
      import com.not.testComApi 1.0
      
      Window {
          PlcCom{
               id:p2
      
               port:62944
      
               hostAdr: "10.81.4.108"
               request : "myRequest"
               Component.onCompleted: {         // i also tryed   
                   //p2.hostAdr = "10.81.4.108"
                   //p2.port = 62944
                   //request =  "myRequest"
               }
           }
      

      the problem is my object is created with default property values, this line in PlcCom ctor

       qDebug()<<"connecting : " << m_hostAdr << ":"<<m_port;
      

      will output :

      connecting : "127.0.0.1" : 0 but i expect 10.81.4.108:62944

      Can someone tell me what i'm missing please ?

      J.HilkJ Offline
      J.HilkJ Offline
      J.Hilk
      Moderators
      wrote on last edited by
      #2

      hi @LeLev

      IIRC your setPort function has to be markt as slot

      public slots:
      void setPort(int port)
          {
              if (m_port == port)
                  return;
              m_port = port;
              emit portChanged(m_port);
          }
      

      I think the QML-CPP communication requires Q_OBJECT macro and proper slot macros to work correctly.


      Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


      Q: What's that?
      A: It's blue light.
      Q: What does it do?
      A: It turns blue.

      ODБOïO 1 Reply Last reply
      2
      • J.HilkJ J.Hilk

        hi @LeLev

        IIRC your setPort function has to be markt as slot

        public slots:
        void setPort(int port)
            {
                if (m_port == port)
                    return;
                m_port = port;
                emit portChanged(m_port);
            }
        

        I think the QML-CPP communication requires Q_OBJECT macro and proper slot macros to work correctly.

        ODБOïO Offline
        ODБOïO Offline
        ODБOï
        wrote on last edited by ODБOï
        #3

        Thank you
        @J.Hilk said in Registering an Instantiable Object Type:

        has to be markt as slot

        now it is but still not initialized correctly

        J.HilkJ 1 Reply Last reply
        0
        • ODБOïO ODБOï

          Thank you
          @J.Hilk said in Registering an Instantiable Object Type:

          has to be markt as slot

          now it is but still not initialized correctly

          J.HilkJ Offline
          J.HilkJ Offline
          J.Hilk
          Moderators
          wrote on last edited by
          #4

          @LeLev mmh,
          do you initialize the QObject parent correctly?


          Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


          Q: What's that?
          A: It's blue light.
          Q: What does it do?
          A: It turns blue.

          ODБOïO 1 Reply Last reply
          0
          • J.HilkJ J.Hilk

            @LeLev mmh,
            do you initialize the QObject parent correctly?

            ODБOïO Offline
            ODБOïO Offline
            ODБOï
            wrote on last edited by
            #5

            @J.Hilk please see the full class code

            class PlcCom : public QObject
            {
                Q_OBJECT
            
                Q_PROPERTY(QString request READ request WRITE setRequest NOTIFY requestChanged)
                Q_PROPERTY(QString stringValue READ stringValue WRITE setStringValue NOTIFY stringValueChanged)
                Q_PROPERTY(QString hostAdr READ hostAdr WRITE setHostAdr NOTIFY hostAdrChanged)
                Q_PROPERTY(int port READ port WRITE setPort NOTIFY portChanged)
            
            public:
                explicit PlcCom(QObject *parent = nullptr);
            
            public slots:
            
                QString request() const {return m_request;}
                void setRequest(QString request)
                {
                    if (m_request == request)
                        return;
            
                    m_request = request;
                    emit requestChanged(m_request);
                }
            
                QString stringValue() const{return m_stringValue;}
                void setStringValue(QString stringValue)
                {
                    m_stringValue = stringValue;    
                    emit stringValueChanged(m_stringValue);
                }
            
                QString hostAdr() const{ return m_hostAdr;}
                void setHostAdr(QString hostAdr)
                {
                    if (m_hostAdr == hostAdr)
                        return;
            
                    m_hostAdr = hostAdr;
                    emit hostAdrChanged(m_hostAdr);
                }
            
                int port() const{return m_port;}
            
                void setPort(int port)
                {
                    if (m_port == port)
                        return;
            
                    m_port = port;
                    emit portChanged(m_port);
                }
            
            signals:
                void requestChanged(QString request);
                void stringValueChanged(QString stringValue);
                void hostAdrChanged(QString hostAdr);
                void portChanged(int port);
            
            private :
                void socketConnected();
                void socketDisconnected();
                void responseReady();
            
            private:
                QString m_request;
                QString m_stringValue;
                QString m_hostAdr;
                int m_port;
                QTcpSocket *sk;
            };
            
            
            PlcCom::PlcCom(QObject *parent)
                : QObject(parent)
            {
                sk = new QTcpSocket(this);
            
                QObject::connect(sk,&QTcpSocket::connected,this,&PlcCom::socketConnected);
                QObject::connect(sk,&QTcpSocket::disconnected,this,&PlcCom::socketDisconnected);
                QObject::connect(sk,&QTcpSocket::readyRead,this,&PlcCom::responseReady);
                connect(sk, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error),
                        [=](QAbstractSocket::SocketError err){
                    qDebug()<<"SocketError";
                });
            
            
                //qDebug()<<"connecting : " << m_hostAdr << ":"<<m_port; // here output default values
            
            
                // BADFIX : TODO   improve , QML properties not set directly ?
                QObject::connect(this,&PlcCom::hostAdrChanged,[&](){ // here everything is initialized with qml values
                    qDebug()<<"connecting : " << m_hostAdr << ":"<<m_port;
                    sk->connectToHost(QHostAddress(m_hostAdr),static_cast<quint16>(m_port));
            
                    if(!sk->waitForConnected(5000))
                    {
                        qDebug() << "Error: " << sk->errorString();
                        return;
                    }
                });
            }
            
            void PlcCom::socketConnected()
            {
                qDebug("CONNECTED.");
                QString c = m_request; 
                qDebug()<<"SENDING COMMAND : " << c;
                c.append("\n");
                sk->write(c.toLatin1(),c.length());
            }
            
            void PlcCom::socketDisconnected()
            {
                qDebug("DISCONNECTED...");
            }
            
            void PlcCom::responseReady()
            {
                qDebug() << "reading...";
                setStringValue(sk->readAll());
            }
            
            
            J.HilkJ 1 Reply Last reply
            0
            • ODБOïO ODБOï

              @J.Hilk please see the full class code

              class PlcCom : public QObject
              {
                  Q_OBJECT
              
                  Q_PROPERTY(QString request READ request WRITE setRequest NOTIFY requestChanged)
                  Q_PROPERTY(QString stringValue READ stringValue WRITE setStringValue NOTIFY stringValueChanged)
                  Q_PROPERTY(QString hostAdr READ hostAdr WRITE setHostAdr NOTIFY hostAdrChanged)
                  Q_PROPERTY(int port READ port WRITE setPort NOTIFY portChanged)
              
              public:
                  explicit PlcCom(QObject *parent = nullptr);
              
              public slots:
              
                  QString request() const {return m_request;}
                  void setRequest(QString request)
                  {
                      if (m_request == request)
                          return;
              
                      m_request = request;
                      emit requestChanged(m_request);
                  }
              
                  QString stringValue() const{return m_stringValue;}
                  void setStringValue(QString stringValue)
                  {
                      m_stringValue = stringValue;    
                      emit stringValueChanged(m_stringValue);
                  }
              
                  QString hostAdr() const{ return m_hostAdr;}
                  void setHostAdr(QString hostAdr)
                  {
                      if (m_hostAdr == hostAdr)
                          return;
              
                      m_hostAdr = hostAdr;
                      emit hostAdrChanged(m_hostAdr);
                  }
              
                  int port() const{return m_port;}
              
                  void setPort(int port)
                  {
                      if (m_port == port)
                          return;
              
                      m_port = port;
                      emit portChanged(m_port);
                  }
              
              signals:
                  void requestChanged(QString request);
                  void stringValueChanged(QString stringValue);
                  void hostAdrChanged(QString hostAdr);
                  void portChanged(int port);
              
              private :
                  void socketConnected();
                  void socketDisconnected();
                  void responseReady();
              
              private:
                  QString m_request;
                  QString m_stringValue;
                  QString m_hostAdr;
                  int m_port;
                  QTcpSocket *sk;
              };
              
              
              PlcCom::PlcCom(QObject *parent)
                  : QObject(parent)
              {
                  sk = new QTcpSocket(this);
              
                  QObject::connect(sk,&QTcpSocket::connected,this,&PlcCom::socketConnected);
                  QObject::connect(sk,&QTcpSocket::disconnected,this,&PlcCom::socketDisconnected);
                  QObject::connect(sk,&QTcpSocket::readyRead,this,&PlcCom::responseReady);
                  connect(sk, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error),
                          [=](QAbstractSocket::SocketError err){
                      qDebug()<<"SocketError";
                  });
              
              
                  //qDebug()<<"connecting : " << m_hostAdr << ":"<<m_port; // here output default values
              
              
                  // BADFIX : TODO   improve , QML properties not set directly ?
                  QObject::connect(this,&PlcCom::hostAdrChanged,[&](){ // here everything is initialized with qml values
                      qDebug()<<"connecting : " << m_hostAdr << ":"<<m_port;
                      sk->connectToHost(QHostAddress(m_hostAdr),static_cast<quint16>(m_port));
              
                      if(!sk->waitForConnected(5000))
                      {
                          qDebug() << "Error: " << sk->errorString();
                          return;
                      }
                  });
              }
              
              void PlcCom::socketConnected()
              {
                  qDebug("CONNECTED.");
                  QString c = m_request; 
                  qDebug()<<"SENDING COMMAND : " << c;
                  c.append("\n");
                  sk->write(c.toLatin1(),c.length());
              }
              
              void PlcCom::socketDisconnected()
              {
                  qDebug("DISCONNECTED...");
              }
              
              void PlcCom::responseReady()
              {
                  qDebug() << "reading...";
                  setStringValue(sk->readAll());
              }
              
              
              J.HilkJ Offline
              J.HilkJ Offline
              J.Hilk
              Moderators
              wrote on last edited by
              #6

              @LeLev
              I can't reproduce this,
              take this minimal example:

              #ifndef MYCLASS_H
              #define MYCLASS_H
              
              #include <QObject>
              #include <QDebug>
              
              class myClass : public QObject
              {
                  Q_OBJECT
                  Q_PROPERTY(QString hostAdr READ hostAdr WRITE setHostAdr NOTIFY hostAdrChanged)
              public:
                  explicit myClass(QObject *parent = nullptr) :QObject(parent)
                  {
                      connect(this, &myClass::hostAdrChanged, this, [](QString hostAdr)->void{
                          qDebug() <<hostAdr;
                      });
                  }
              
                  const QString &hostAdr() const
                  {
                      return m_hostAdr;
                  }
              
              signals:
                  void hostAdrChanged(const QString &hostAdr);
              
              public slots:
              
              void setHostAdr(const QString &hostAdr)
              {
                  if (m_hostAdr == hostAdr)
                      return;
              
                  m_hostAdr = hostAdr;
                  emit hostAdrChanged(m_hostAdr);
              }
              
              private:
                  QString m_hostAdr;
              };
              
              #endif // MYCLASS_H
              
              
              //main.cpp
              int main(int argc, char *argv[])
              {
                  QApplication app(argc, argv);
              
                  qmlRegisterType<myClass>("com.not.testComApi", 1, 0, "PlcCom");
              
                  QQmlApplicationEngine engine;
              
                  engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                  if (engine.rootObjects().isEmpty())
                      return -1;
              }
              
              import QtQuick 2.12
              import QtQuick.Controls 2.5
              
              import com.not.testComApi 1.0
              
              ApplicationWindow {
                  visible:true
                  width:500; height:500
              
                  PlcCom{
                      hostAdr: "abcd"
                  }
              }
              

              the changed signal is emitted fine with the correct string


              Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


              Q: What's that?
              A: It's blue light.
              Q: What does it do?
              A: It turns blue.

              ODБOïO 1 Reply Last reply
              1
              • J.HilkJ J.Hilk

                @LeLev
                I can't reproduce this,
                take this minimal example:

                #ifndef MYCLASS_H
                #define MYCLASS_H
                
                #include <QObject>
                #include <QDebug>
                
                class myClass : public QObject
                {
                    Q_OBJECT
                    Q_PROPERTY(QString hostAdr READ hostAdr WRITE setHostAdr NOTIFY hostAdrChanged)
                public:
                    explicit myClass(QObject *parent = nullptr) :QObject(parent)
                    {
                        connect(this, &myClass::hostAdrChanged, this, [](QString hostAdr)->void{
                            qDebug() <<hostAdr;
                        });
                    }
                
                    const QString &hostAdr() const
                    {
                        return m_hostAdr;
                    }
                
                signals:
                    void hostAdrChanged(const QString &hostAdr);
                
                public slots:
                
                void setHostAdr(const QString &hostAdr)
                {
                    if (m_hostAdr == hostAdr)
                        return;
                
                    m_hostAdr = hostAdr;
                    emit hostAdrChanged(m_hostAdr);
                }
                
                private:
                    QString m_hostAdr;
                };
                
                #endif // MYCLASS_H
                
                
                //main.cpp
                int main(int argc, char *argv[])
                {
                    QApplication app(argc, argv);
                
                    qmlRegisterType<myClass>("com.not.testComApi", 1, 0, "PlcCom");
                
                    QQmlApplicationEngine engine;
                
                    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                    if (engine.rootObjects().isEmpty())
                        return -1;
                }
                
                import QtQuick 2.12
                import QtQuick.Controls 2.5
                
                import com.not.testComApi 1.0
                
                ApplicationWindow {
                    visible:true
                    width:500; height:500
                
                    PlcCom{
                        hostAdr: "abcd"
                    }
                }
                

                the changed signal is emitted fine with the correct string

                ODБOïO Offline
                ODБOïO Offline
                ODБOï
                wrote on last edited by ODБOï
                #7

                @J.Hilk thank you very much.
                I did the same way (see my previous post), only i wonder why i have to handle that hostAdrChanged signal ? i want to create the object directly with right parameter values, QML side.

                In my constructor

                qDebug()<<"connecting : " << m_hostAdr << ":"<<m_port;
                

                this will output default values,
                but if i do

                QObject::connect(this,&PlcCom::hostAdrChanged,[&](){ 
                       qDebug()<<"connecting : " << m_hostAdr << ":"<<m_port;
                       
                

                here everything is initialized with qml values

                J.HilkJ 1 Reply Last reply
                0
                • ODБOïO ODБOï

                  @J.Hilk thank you very much.
                  I did the same way (see my previous post), only i wonder why i have to handle that hostAdrChanged signal ? i want to create the object directly with right parameter values, QML side.

                  In my constructor

                  qDebug()<<"connecting : " << m_hostAdr << ":"<<m_port;
                  

                  this will output default values,
                  but if i do

                  QObject::connect(this,&PlcCom::hostAdrChanged,[&](){ 
                         qDebug()<<"connecting : " << m_hostAdr << ":"<<m_port;
                         
                  

                  here everything is initialized with qml values

                  J.HilkJ Offline
                  J.HilkJ Offline
                  J.Hilk
                  Moderators
                  wrote on last edited by J.Hilk
                  #8

                  @LeLev
                  well the c++ part is initialized first. You class gets initiated -> call of the constructor

                  then it's passed to the qml engine, then the values from there are taken and set.

                  if you want to initialize your values from qml side only, you can do that to.

                  IIRC there is QQmlParserStatus Class

                  When your class inherits from that as well as from QObject you can override the virtual componentComplete function and do your initialization there.

                  That one is called together with the QML Component.onCompleted: ...signal


                  Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                  Q: What's that?
                  A: It's blue light.
                  Q: What does it do?
                  A: It turns blue.

                  ODБOïO 1 Reply Last reply
                  2
                  • J.HilkJ J.Hilk

                    @LeLev
                    well the c++ part is initialized first. You class gets initiated -> call of the constructor

                    then it's passed to the qml engine, then the values from there are taken and set.

                    if you want to initialize your values from qml side only, you can do that to.

                    IIRC there is QQmlParserStatus Class

                    When your class inherits from that as well as from QObject you can override the virtual componentComplete function and do your initialization there.

                    That one is called together with the QML Component.onCompleted: ...signal

                    ODБOïO Offline
                    ODБOïO Offline
                    ODБOï
                    wrote on last edited by
                    #9

                    @J.Hilk Yes thank you again! i was reading this also : https://doc.qt.io/qt-5/qtqml-cppintegration-definetypes.html#receiving-notifications-for-object-initialization

                    1 Reply Last reply
                    1

                    • Login

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