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

QT中的元对象系统(二):创建自定义的QT类型 收藏
       原创文章,转载请注明出处,谢谢!       
       作者:清林,博客名:飞空静渡


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

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

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


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

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

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


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

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

view plaincopy to clipboardprint?
#ifndef MESSAGE_H  
#define MESSAGE_H  
#include <QDebug>  
#include <QMetaType>  
#include <QStringList>  
class Message  
{  
public:  
    Message();  
    Message(const Message &other);  
    ~Message();  
    Message(const QString &body, const QStringList &headers);  
    QString body() const;  
    QStringList headers() const;  
private:  
    QString m_body;  
    QStringList m_headers;  
};  
Q_DECLARE_METATYPE(Message);  
QDebug &operator<<(QDebug &dbg, const Message &message);  
#endif 
 #ifndef MESSAGE_H
 #define MESSAGE_H
 #include <QDebug>
 #include <QMetaType>
 #include <QStringList>
 class Message
 {
 public:
     Message();
     Message(const Message &other);
     ~Message();
     Message(const QString &body, const QStringList &headers);
     QString body() const;
     QStringList headers() const;
 private:
     QString m_body;
     QStringList m_headers;
 };
 Q_DECLARE_METATYPE(Message);
 QDebug &operator<<(QDebug &dbg, const Message &message);
 #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?
#include "message.h"  
 Message::Message()  
 {  
 }  
 Message::Message(const Message &other)  
 {  
     m_body = other.m_body;  
     m_headers = other.m_headers;  
 }  
 Message::~Message()  
 {  
 }  
 Message::Message(const QString &body, const QStringList &headers)  
 {  
     m_body = body;  
     m_headers = headers;  
 }  
 QDebug &operator<<(QDebug &dbg, const Message &message)  
 {  
     QStringList pieces = message.body().split("/r/n", QString::SkipEmptyParts);  
     if (pieces.isEmpty())  
         dbg.nospace() << "Message()";  
     else if (pieces.size() == 1)  
         dbg.nospace() << "Message(" << pieces.first() << ")";  
     else 
         dbg.nospace() << "Message(" << pieces.first() << " ...)";  
     return dbg.maybeSpace();  
 }  
 QString Message::body() const 
 {  
     return m_body;  
 }  
 QStringList Message::headers() const 
 {  
     return m_headers;  
 } 
#include "message.h"
 Message::Message()
 {
 }
 Message::Message(const Message &other)
 {
     m_body = other.m_body;
     m_headers = other.m_headers;
 }
 Message::~Message()
 {
 }
 Message::Message(const QString &body, const QStringList &headers)
 {
     m_body = body;
     m_headers = headers;
 }
 QDebug &operator<<(QDebug &dbg, const Message &message)
 {
     QStringList pieces = message.body().split("/r/n", QString::SkipEmptyParts);
     if (pieces.isEmpty())
         dbg.nospace() << "Message()";
     else if (pieces.size() == 1)
         dbg.nospace() << "Message(" << pieces.first() << ")";
     else
         dbg.nospace() << "Message(" << pieces.first() << " ...)";
     return dbg.maybeSpace();
 }
 QString Message::body() const
 {
     return m_body;
 }
 QStringList Message::headers() const
 {
     return m_headers;
 }


最后看下我们的main函数。

view plaincopy to clipboardprint?
#include <QCoreApplication>  
 #include <QVariant>  
 #include "message.h"  
 int main(int argc, char *argv[])  
 {  
     QCoreApplication app(argc, argv);  
     QStringList headers;  
     headers << "Subject: Hello World" 
             << "From: [email protected] ";  
     QString body = "This is a test./r/n";  
     Message message(body, headers);  
     qDebug() << "Original:" << message;  
     QVariant stored;  
     stored.setValue(message);  
     qDebug() << "Stored:" << stored;  
     Message retrieved = stored.value<Message>();  
     qDebug() << "Retrieved:" << retrieved;  
     retrieved = qVariantValue<Message>(stored);  
     qDebug() << "Retrieved:" << retrieved;  
     return 0;  
 } 
#include <QCoreApplication>
 #include <QVariant>
 #include "message.h"
 int main(int argc, char *argv[])
 {
     QCoreApplication app(argc, argv);
     QStringList headers;
     headers << "Subject: Hello World"
             << "From: [email protected] ";
     QString body = "This is a test./r/n";
     Message message(body, headers);
     qDebug() << "Original:" << message;
     QVariant stored;
     stored.setValue(message);
     qDebug() << "Stored:" << stored;
     Message retrieved = stored.value<Message>();
     qDebug() << "Retrieved:" << retrieved;
     retrieved = qVariantValue<Message>(stored);
     qDebug() << "Retrieved:" << retrieved;
     return 0;
 }

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


     QVariant stored;
     stored.setValue(message);
而从 QVariant中获得我们的对象可以这样:


Message retrieved = stored.value<Message>();
pro文件:


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

 

你可能感兴趣的:(QT中的元对象系统(二):创建自定义的QT类型 收藏)