QT中的元对象系统(二):创建自定义的QT类型

来源:互联网 发布:社区源码 编辑:程序博客网 时间:2024/05/01 16:50

     原创文章,转载请注明出处,谢谢!       
       作者:清林,博客名:飞空静渡

原文:http://blog.csdn.net/fjb2080/archive/2009/12/10/4977342.aspx


我们在使用QT编程时,难免要定义自己需要的类型,但像QT自己的类型如QSzie、QString之类的,都是可以存储在QViriant中的,并且这些QT的类型是可以用在基于QObject类的类型属性中和基于信号和槽的发生机制中。

如果我们想要我们自己自定义的类型可以有QT自己类型的功能的话,我们就必须注册我们的类型到QT中,这样我们才可以在我们在信号和槽的通讯机制中使用我们的类型。

在我们想要把我们的类型注册到QT中,我们必须满足QMedaType类型的要求,这有三点是必须的要求(以后章节说的也要满足这三点要求)。

1、必须要有一个公有的构造函数。

2、必须要有一个公有的拷贝构造函数。

3、必须要有一个公有的虚构函数。


下面使用QT文档中的一个例子来说明:

第一步:我们首先可以定义一个满足上面三点要求的自定义的类。

view plaincopy to clipboardprint?
  1. #ifndef MESSAGE_H  
  2. #define MESSAGE_H  
  3. #include <QDebug>  
  4. #include <QMetaType>  
  5. #include <QStringList>  
  6. class Message  
  7. {  
  8. public:  
  9.     Message();  
  10.     Message(const Message &other);  
  11.     ~Message();  
  12.     Message(const QString &body, const QStringList &headers);  
  13.     QString body() const;  
  14.     QStringList headers() const;  
  15. private:  
  16.     QString m_body;  
  17.     QStringList m_headers;  
  18. };  
  19. Q_DECLARE_METATYPE(Message);  
  20. QDebug &operator<<(QDebug &dbg, const Message &message);  
  21. #endif  


第二步:注册我们的类型

我们的自定义的类型,在QT中的QVariant中的,因为在QVariant中并不知道怎么存储和获取我们的类型。因此我们就必须使我们的类型成为和QString一样的通用类型,这就需要QT中的QMetaType来完成了。我们需要调用Q_DECLARE_METATYPE这个宏来完成。

 Q_DECLARE_METATYPE(Message);

这就可以使我们的Message可以存储在QVariant中了。Q_DECLARE_METATYPE可以使我们的类型使用在信号的参数中,但是直接使用在信号-槽的通讯中的,但不可以用在基于消息队列中的信号-槽的机制中的,例如我们在线程中的通讯,上面的那种定义就做不到了。这是因为,上面的那种定义是用宏来静态定义的,在QT中的元对象系统中并不知道在运行时怎么创建和销毁我们的自定义的对象。我将在后一章讲解我们自定义的类型完全用在信号-槽的通讯机制中的做法。


这是Message的实现代码:

view plaincopy to clipboardprint?
  1. #include "message.h"  
  2.  Message::Message()  
  3.  {  
  4.  }  
  5.  Message::Message(const Message &other)  
  6.  {  
  7.      m_body = other.m_body;  
  8.      m_headers = other.m_headers;  
  9.  }  
  10.  Message::~Message()  
  11.  {  
  12.  }  
  13.  Message::Message(const QString &body, const QStringList &headers)  
  14.  {  
  15.      m_body = body;  
  16.      m_headers = headers;  
  17.  }  
  18.  QDebug &operator<<(QDebug &dbg, const Message &message)  
  19.  {  
  20.      QStringList pieces = message.body().split("/r/n", QString::SkipEmptyParts);  
  21.      if (pieces.isEmpty())  
  22.          dbg.nospace() << "Message()";  
  23.      else if (pieces.size() == 1)  
  24.          dbg.nospace() << "Message(" << pieces.first() << ")";  
  25.      else  
  26.          dbg.nospace() << "Message(" << pieces.first() << " ...)";  
  27.      return dbg.maybeSpace();  
  28.  }  
  29.  QString Message::body() const  
  30.  {  
  31.      return m_body;  
  32.  }  
  33.  QStringList Message::headers() const  
  34.  {  
  35.      return m_headers;  
  36.  }  



最后看下我们的main函数。

view plaincopy to clipboardprint?
  1. #include <QCoreApplication>  
  2.  #include <QVariant>  
  3.  #include "message.h"  
  4.  int main(int argc, char *argv[])  
  5.  {  
  6.      QCoreApplication app(argc, argv);  
  7.      QStringList headers;  
  8.      headers << "Subject: Hello World"  
  9.              << "From: qt-info@nokia.com";  
  10.      QString body = "This is a test./r/n";  
  11.      Message message(body, headers);  
  12.      qDebug() << "Original:" << message;  
  13.      QVariant stored;  
  14.      stored.setValue(message);  
  15.      qDebug() << "Stored:" << stored;  
  16.      Message retrieved = stored.value<Message>();  
  17.      qDebug() << "Retrieved:" << retrieved;  
  18.      retrieved = qVariantValue<Message>(stored);  
  19.      qDebug() << "Retrieved:" << retrieved;  
  20.      return 0;  
  21.  }  


我们在注册我们的Message类后,我们就可以使我们的Message类对象存储在我们的QVariant的对象中了。在main函数中,我们可以看到

     QVariant stored;

stored.setValue(message);

而从QVariant中获得我们的对象可以这样:

Message retrieved = stored.value<Message>();

pro文件:

 HEADERS   = message.h

SOURCES = main.cpp /

message.cpp

下一章讲解用这个例子用在信号-槽的通讯机制中,后一章将讲解自定义类型在消息队列的信号-槽的机制,即在多线程通讯中使自定义类型在信号-槽中的运用。