Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Using QVariant to store custom types in Qt6.5.1
QtWS25 Last Chance

Using QVariant to store custom types in Qt6.5.1

Scheduled Pinned Locked Moved Solved General and Desktop
qvariant
4 Posts 2 Posters 1.2k 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.
  • S Offline
    S Offline
    szmf
    wrote on 21 Nov 2023, 14:15 last edited by
    #1

    In all the tutorials I've found, it is mentioned that "you must use Q_DECLARE_METATYPE to declare custom types to the Qt meta-system."
    I created a example for testing and found that I can directly call QVariant::setValue() to store custom types without using Q_DECLARE_METATYPE.

    #include <QCoreApplication>
    #include <QVariant>
    
    struct Entity
    {
        int value;
        QString str;
    };
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        Entity entity;
        entity.value = 12345;
        entity.str = "hello, world";
    
        QVariant variant;
        variant.setValue(entity);
    
        Entity receiver = variant.value<Entity>();
        qDebug() << receiver.value;
        qDebug() << receiver.str;
    
        return a.exec();
    }
    

    When is it necessary to use Q_DECLARE_METATYPE?

    P 1 Reply Last reply 21 Nov 2023, 15:32
    0
    • S szmf
      21 Nov 2023, 14:15

      In all the tutorials I've found, it is mentioned that "you must use Q_DECLARE_METATYPE to declare custom types to the Qt meta-system."
      I created a example for testing and found that I can directly call QVariant::setValue() to store custom types without using Q_DECLARE_METATYPE.

      #include <QCoreApplication>
      #include <QVariant>
      
      struct Entity
      {
          int value;
          QString str;
      };
      
      int main(int argc, char *argv[])
      {
          QCoreApplication a(argc, argv);
      
          Entity entity;
          entity.value = 12345;
          entity.str = "hello, world";
      
          QVariant variant;
          variant.setValue(entity);
      
          Entity receiver = variant.value<Entity>();
          qDebug() << receiver.value;
          qDebug() << receiver.str;
      
          return a.exec();
      }
      

      When is it necessary to use Q_DECLARE_METATYPE?

      P Offline
      P Offline
      Pl45m4
      wrote on 21 Nov 2023, 15:32 last edited by
      #2

      @szmf

      When you want to do this

      public:
          void onEntityChanged(Entity e);
      
      signal:
          void entityChanged(Entity e);
      
      
      
      connect(this, &MyWidget::entityChanged, otherWidget, &OtherWidget::onEntityChanged);
      

      You need to register Entity in order to fully use it in the meta-object system including sending it via signal


      If debugging is the process of removing software bugs, then programming must be the process of putting them in.

      ~E. W. Dijkstra

      S 1 Reply Last reply 22 Nov 2023, 02:21
      1
      • P Pl45m4
        21 Nov 2023, 15:32

        @szmf

        When you want to do this

        public:
            void onEntityChanged(Entity e);
        
        signal:
            void entityChanged(Entity e);
        
        
        
        connect(this, &MyWidget::entityChanged, otherWidget, &OtherWidget::onEntityChanged);
        

        You need to register Entity in order to fully use it in the meta-object system including sending it via signal

        S Offline
        S Offline
        szmf
        wrote on 22 Nov 2023, 02:21 last edited by
        #3

        @Pl45m4 Thank you for your response. I added a Sender class to send Entity objects, and the code still runs fine.

        // head.h
        #pragma once
        #include <QCoreApplication>
        #include <QVariant>
        
        struct Entity
        {
            int value;
            QString str;
        };
        
        class Sender: public QObject
        {
            Q_OBJECT
        
        signals:
            void sig_sendEntity(Entity e);
        
        public slots:
            void slot_getEntity(Entity e);
        };
        
        // main.cpp
        #include "head.h"
        
        void Sender::slot_getEntity(Entity e)
        {
            qDebug() << "slot get Entity value: " << e.value << ", str: " << e.str;
        }
        
        int main(int argc, char *argv[])
        {
            QCoreApplication a(argc, argv);
        
            Entity entity;
            entity.value = 12345;
            entity.str = "hello, world";
        
            QVariant variant;
            variant.setValue(entity);
        
            Entity receiver = variant.value<Entity>();
            qDebug() << receiver.value;
            qDebug() << receiver.str;
        
            Sender sender;
            QObject::connect(&sender, &Sender::sig_sendEntity, &sender, &Sender::slot_getEntity);
            emit sender.sig_sendEntity(entity);
        
            return a.exec();
        }
        

        Does the Qt configuration environment affect the execution of the program?

        P 1 Reply Last reply 22 Nov 2023, 04:54
        0
        • S szmf
          22 Nov 2023, 02:21

          @Pl45m4 Thank you for your response. I added a Sender class to send Entity objects, and the code still runs fine.

          // head.h
          #pragma once
          #include <QCoreApplication>
          #include <QVariant>
          
          struct Entity
          {
              int value;
              QString str;
          };
          
          class Sender: public QObject
          {
              Q_OBJECT
          
          signals:
              void sig_sendEntity(Entity e);
          
          public slots:
              void slot_getEntity(Entity e);
          };
          
          // main.cpp
          #include "head.h"
          
          void Sender::slot_getEntity(Entity e)
          {
              qDebug() << "slot get Entity value: " << e.value << ", str: " << e.str;
          }
          
          int main(int argc, char *argv[])
          {
              QCoreApplication a(argc, argv);
          
              Entity entity;
              entity.value = 12345;
              entity.str = "hello, world";
          
              QVariant variant;
              variant.setValue(entity);
          
              Entity receiver = variant.value<Entity>();
              qDebug() << receiver.value;
              qDebug() << receiver.str;
          
              Sender sender;
              QObject::connect(&sender, &Sender::sig_sendEntity, &sender, &Sender::slot_getEntity);
              emit sender.sig_sendEntity(entity);
          
              return a.exec();
          }
          

          Does the Qt configuration environment affect the execution of the program?

          P Offline
          P Offline
          Pl45m4
          wrote on 22 Nov 2023, 04:54 last edited by Pl45m4
          #4

          @szmf

          It might work when on the same thread (also you should register it anyway) but as soon as you have QueuedConnections this will probably fail without registering the type globally.

          • https://doc.qt.io/qt-6/custom-types.html#overview

          The part here even says, that declaring is necessary for direct signal and slot connections:

          The Message class only needs a suitable implementation in order to be usable. However, Qt's type system will not be able to understand how to store, retrieve and serialize instances of this class without some assistance. For example, we will be unable to store Message values in QVariant.

          The class in Qt responsible for custom types is QMetaType. To make the type known to this class, we invoke the Q_DECLARE_METATYPE() macro on the class in the header file where it is defined:
          Q_DECLARE_METATYPE(Message);

          This now makes it possible for Message values to be stored in QVariant objects and retrieved later. See the Custom Type Example for code that demonstrates this.

          The Q_DECLARE_METATYPE() macro also makes it possible for these values to be used as arguments to signals, but only in direct signal-slot connections. To make the custom type generally usable with the signals and slots mechanism, we need to perform some extra work.

          As stated reading further here:

          Although the declaration in the previous section makes the type available for use in direct signal-slot connections, it cannot be used for queued signal-slot connections, such as those that are made between objects in different threads. This is because the meta-object system does not know how to handle creation and destruction of objects of the custom type at run-time.

          To enable creation of objects at run-time, call the qRegisterMetaType() template function to register it with the meta-object system. This also makes the type available for queued signal-slot communication as long as you call it before you make the first connection that uses the type.


          If debugging is the process of removing software bugs, then programming must be the process of putting them in.

          ~E. W. Dijkstra

          1 Reply Last reply
          1
          • S szmf has marked this topic as solved on 22 Nov 2023, 05:32

          1/4

          21 Nov 2023, 14:15

          • Login

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