QT 中的元对象系统(二):创建自定义的QT类型
2012-08-07 07:11
459 查看
本文 转载至于: http://blog.163.com/jx_yp/blog/static/1197044592011119103432795/
我们在使用QT编程时,难免要定义自己需要的类型,但像QT自己的类型如QSzie、QString之类的,都是可以存储在QViriant中的,并且这些QT的类型是可以用在基于QObject类的类型属性中和基于信号和槽的发生机制中。
如果我们想要我们自己自定义的类型可以有QT自己类型的功能的话,我们就必须注册我们的类型到QT中,这样我们才可以在我们在信号和槽的通讯机制中使用我们的类型。
在我们想要把我们的类型注册到QT中,我们必须满足QMedaType类型的要求,这有三点是必须的要求(以后章节说的也要满足这三点要求)。
1、必须要有一个公有的构造函数。
2、必须要有一个公有的拷贝构造函数。
3、必须要有一个公有的虚构函数。
下面使用QT文档中的一个例子来说明:
第一步:我们首先可以定义一个满足上面三点要求的自定义的类。
#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这个宏来完成。
这 就可以使我们的Message可以存储在QVariant中了。Q_DECLARE_METATYPE可以使我们的类型使用在信号的参数中,但是直接使用 在信号-槽的通讯中的,但不可以用在基于消息队列中的信号-槽的机制中的,例如我们在线程中的通讯,上面的那种定义就做不到了。这是因为,上面的那种定义 是用宏来静态定义的,在QT中的元对象系统中并不知道在运行时怎么创建和销毁我们的自定义的对象。我将在后一章讲解我们自定义的类型完全用在信号-槽的通 讯机制中的做法。
这是Message的实现代码:
#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函数。
#include <QCoreApplication>
#include <QVariant>
#include "message.h"
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QStringList headers;
headers << "Subject: Hello World"
<< "From: qt-info@nokia.com";
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中获得我们的对象可以这样:
pro文件:
下一章讲解用这个例子用在信号-槽的通讯机制中,后一章将讲解自定义类型在消息队列的信号-槽的机制,即在多线程通讯中使自定义类型在信号-槽中的运用。
我们在使用QT编程时,难免要定义自己需要的类型,但像QT自己的类型如QSzie、QString之类的,都是可以存储在QViriant中的,并且这些QT的类型是可以用在基于QObject类的类型属性中和基于信号和槽的发生机制中。
如果我们想要我们自己自定义的类型可以有QT自己类型的功能的话,我们就必须注册我们的类型到QT中,这样我们才可以在我们在信号和槽的通讯机制中使用我们的类型。
在我们想要把我们的类型注册到QT中,我们必须满足QMedaType类型的要求,这有三点是必须的要求(以后章节说的也要满足这三点要求)。
1、必须要有一个公有的构造函数。
2、必须要有一个公有的拷贝构造函数。
3、必须要有一个公有的虚构函数。
下面使用QT文档中的一个例子来说明:
第一步:我们首先可以定义一个满足上面三点要求的自定义的类。
#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的实现代码:
#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函数。
#include <QCoreApplication>
#include <QVariant>
#include "message.h"
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QStringList headers;
headers << "Subject: Hello World"
<< "From: qt-info@nokia.com";
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类型
- QT中的元对象系统(二):创建自定义的QT类型 收藏
- QT中的元对象系统(二):创建自定义的QT类型
- QT中的元对象系统(二):创建自定义的QT类型
- QT中的元对象系统(二):创建自定义的QT类型
- QT中的元对象系统(二):创建自定义的QT类型
- 创建自定义Qt类型
- Qt之创建自定义类型
- Qt之创建自定义类型
- Qt中菜单创建及自定义数据类型与QVariant互转
- 创建自定义类型的强类型化集合
- QT 信号槽connect中解决自定义数据类型或数组作为函数参数的问题——QT qRegisterMetaType 注册MetaType——关键:注册自定义数据类型或QMap等容器类
- Symfony2CookBook:如何创建自定义的表单域类型
- 创建moss自定义字段类型实例
- 自定义类型部分知识写一篇博客。 知识点: >结构体类型创建 >结构体初始化 >结构体内存对齐 >位段,位段计算机大小。 >枚举+联合。
- QT 自定义信号与信号槽方法及解决自定义数据类型或数组作为函数参数的问题
- 组合使用构造函数模式和原型模式创建自定义类型
- MOSS创建自定义字段类型
- 如何在Qt中使用自定义数据类型
- 【一步一步学习VBA】创建用户自定义类或者自定义类型