Qt信号槽——传递自定义数据类型
Qt的信号槽机制支持传递int,short,double等C语言的基本类型的变量,也可以传递Qt自己的数据类型。但是在传递用户自己定义的数据类型,或其他数据类型是需要进行注册的。
原因:当一个signal被放到队列(queued)中时,它的参数(arguments)也会被一起放到队列中。这就意味着参数在被传送到slot之前不仅要被拷贝,存储在队列(queue)中。为了能够在队列中存储这些参数(argument),Qt需要去construct、destruct、copy这些对象,而为了让Qt知道怎么去做这些事情,参数的类型需要使用qRegisterMetaType来注册。
参考以下文档: (不得不说Qt的文档是真的好,基本所有问题都可以查看文档解决)
Qt文档:QMetaType Class | Qt Core 5.15.11
原文链接:Qt信号槽机制-传递自定义数据类型(qRegisterMetaType)_宁静致远2021的博客-CSDN博客_qt信号槽传递自定义类型
原文链接:Qt信号槽传递自定义结构体_Liu-Eleven的博客-CSDN博客_qt信号槽传递自定义结构体
1. 方法一
1.1 步骤
-
自定义一种类型,在这个类型所在文件包含头文件:#include <QMetaType>
-
在类型定义完成后,声明自定义类型:Q_DECLARE_METATYPE(Type)
// This example shows a typical use case of Q_DECLARE_METATYPE():
struct MyStruct
{
int i;
...
};
Q_DECLARE_METATYPE(MyStruct)
3.在main()函数中注册自定义类型:template <typename T> int qRegisterMetaType(const char *typeName);
// This example registers the class MyClass:
qRegisterMetaType<MyClass>("MyClass");
如果还希望使用这种类型的引用,还需要注册:qRegisterMetaType<MyClass>("MyClass&");
此方法可以直接在信号槽中使用自己定义的数据类型。
1.2 例程-传递自定义类
// 1.包含头文件
#include <QMetaType>
//必须包含QMetaType,否则会出现下面错误:
//error: expected constructor, destructor, or type conversion before ‘;’ token
#include <QString>
// 2.自定义类型
class MyClass
{
private:
int _count;
QString _text;
public:
MyClass();
MyClass(int, QString);
int count();
QString text();
};
// 3.声明自定义类型
//在自定义类或者结构体等声明后紧接着用宏Q_DECLARE_METATYPE声明自定义自定义数据类型
Q_DECLARE_METATYPE(MyClass)
// 4.在main()函数中注册
int main(int argc, char *argv[])
{
qRegisterMetaType<MyClasst>("MyClass");
qRegisterMetaType<MyClasst>("MyClass&");
QApplication a(argc, argv);
Form w;
w.show();
return a.exec();
}
2. 方法二
第二种方法是通过QVariant类型进行转换。
参考文档:QVariant Class | Qt Core 5.15.11
2.1 例程-传递自定义结构体
2.1.1 定义结构体并注册元对象
// 1.定义结构体
typedef struct student
{
int m_id;
int m_age;
QString m_name;
} student_t;
// 2.注册元对象
Q_DECLARE_METATYPE(student_t)
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void slot_recvStudent(const QVariant varValue);
signals:
void signal_sendStudent(const QVariant varValue);
}
2.1.2 连接信号槽
connect(this, SIGNAL(slot_recvStudent(const QVariant)), this, SLOT(signal_sendStudent(const QVariant)));
2.1.3 使用QVariant打包数据并发送
student_t iStudent;
iStudent.m_id = 1;
iStudent.m_age = 18;
iStudent.m_name = "Box";
QVariant varValue = QVariant::fromValue(iStudent);
emit signal_sendStudent(varValue);
2.1.4 在槽函数中解包并打印
void MainWindow::slot_recvStudent(const QVariant varValue)
{
if (varVlaue.canConvert<student_t>())
{
student_t student = varValue.value<student_t>();
qDebug() << "ID : " << student.m_id;
qDebug() << "Age : " << student.m_age;
qDebug() << "Name : " << student.m_name;
}
}