QT 定义自己的类型 注册和使用
2016-12-11 16:21
369 查看
我们在使用QT编程时,难免要定义自己需要的类型,但像QT自己的类型如QSzie、QString之类的,都是可以存储在QViriant中的,并且这些QT的类型是可以用在基于QObject类的类型属性中和基于信号和槽的发生机制中。如果我们想要我们自己自定义的类型可以有QT自己类型的功能的话,我们就必须注册我们的类型到QT中,这样我们才可以在我们在信号和槽的通讯机制中使用我们的类型。在我们想要把我们的类型注册到QT中,我们必须满足QMedaType类型的要求,这有三点是必须的要求(以后章节说的也要满足这三点要求)。
1、必须要有一个公有的构造函数。2、必须要有一个公有的拷贝构造函数。3、必须要有一个公有的虚构函数。
下面使用QT文档中的一个例子来说明:第一步:我们首先可以定义一个满足上面三点要求的自定义的类。 [cpp] view plain copy print?
#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的实现代码:[cpp] view plain copy print?
#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函数。[cpp] view plain copy print?
#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文件:
下一章讲解用这个例子用在信号-槽的通讯机制中,后一章将讲解自定义类型在消息队列的信号-槽的机制,即在多线程通讯中使自定义类型在信号-槽中的运用。
1、必须要有一个公有的构造函数。2、必须要有一个公有的拷贝构造函数。3、必须要有一个公有的虚构函数。
下面使用QT文档中的一个例子来说明:第一步:我们首先可以定义一个满足上面三点要求的自定义的类。 [cpp] view plain copy print?
#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的实现代码:[cpp] view plain copy print?
#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函数。[cpp] view plain copy print?
#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中使用C++ lib库
- 在ROS中定义并使用自己的消息类型
- Qt学习:线程间共享数据(使用信号槽传递数据,必须提前使用qRegisterMetaType来注册参数的类型)
- 用类名做方法的返回值类型 在学习Java的初始阶段,很多同学使用基本数据类型定义变量和引用类型定义变量以及使用类名做方法的返回值类型常常不知所以。今天我以自己的解读方式和个人的理解作一个简单的解释,和
- Qt使用自定义类型信号槽注册问题
- Qt 界面使用自己定义控件 "提升为"
- Qt自定义类型的注册与使用
- Qt____在信号和槽中使用自己定义的结构体____操作
- Qt QML 入门 — 使用C++定义QML类型
- 在Visual C#中定义和使用自己的特性
- (翻译)在C#中定义和使用自己的特性
- 结合C#在MSSQL中定义和使用自定义类型
- 此网页不允许使用基本类型“System.Web.UI.MasterPage”该类型未注册为安全类型
- 在C#中定义和使用自己的特性
- 使用 Qt 批量选取指定类型文件源代码
- 在C#中定义和使用自己的特性
- (翻译)在C#中定义和使用自己的特性
- (翻译)在C#中定义和使用自己的特性 (转)
- 数据类型和抽象数据类型是如何定义的。二者有何相同和不同之处,抽象数据类型的主要特点是什么?使用抽象数据类型的主要好处是什么?
- JavaScript使用prototype定义对象类型