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

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

原文: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文档中的一个例子来说明:

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

  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的实现代码:

  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函数。

  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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值