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