qt 信号发射结构体

发布时间 2023-09-01 15:05:40作者: 阳光下的小土豆

引用:https://www.cnblogs.com/linuxAndMcu/p/16591417.html

当发送的信号是结构体时:

  • 第一步:定义一个结构体.并在包含该结构体的类里面注册该结构体,通过此方法Q_DECLARE_METATYPE(T).

  • 第二步:作为信号输出时,不能直接传结构体,要先包装一下结构再传出去;接收时,也要拆开包装,才能拿到数据,这里借助 QVariant ;

  • 最后一步:连接信号.

具体实例如下:

MainWindow.h:

 1 #ifndef MAINWINDOW_H
 2 #define MAINWINDOW_H
 3  
 4 #include <QtGui/QMainWindow>
 5 #include<QVariant>
 6  
 7 struct SRT_STUDENT
 8 {
 9     int age;
10     char name[20];
11 };
12 Q_DECLARE_METATYPE(SRT_STUDENT) // 注册结构体
13  
14 class MainWindow : public QMainWindow
15 {
16     Q_OBJECT
17     
18 public:
19     MainWindow(QWidget *parent = 0);
20     ~MainWindow();
21     void sendSig();
22     
23 public slots:
24     void receiveSig(QVariant varValue);
25     
26 signals:
27     void sig_StudentInfo(QVariant varValue); // 自定义的信号
28 };
29  
30 #endif // MAINWINDOW_H

MainWindow.cpp:

 1 #include "mainwindow.h"
 2 #include <QDebug>
 3  
 4 MainWindow::MainWindow(QWidget *parent)
 5     : QMainWindow(parent)
 6 {                     connect(this,SIGNAL(sig_StudentInfo(QVariant)),this,SLOT(receiveSig(QVariant)));
 7 }
 8  
 9 MainWindow::~MainWindow()
10 {
11     
12 }
13  
14 void MainWindow::sendSig()
15 {
16     SRT_STUDENT stu;
17     QVariant varValue; // QT中可以装任何数据的类
18     memset(&stu, 0, sizeof(stu));
19     stu.age = 20;
20     strcpy(stu.name,"lili");
21     varValue.setValue(stu); // 把结构体添加QVariant
22     for(int i=0;i<5;i++)
23     {
24         if(i==4)
25         {
26             emit sig_StudentInfo(varValue);
27             break;
28         }
29     }
30 }
31  
32 void MainWindow::receiveSig(QVariant varValue)
33 {
34     SRT_STUDENT stu1;
35     stu1 = varValue.value<SRT_STUDENT>();
36     qDebug() << "age=" << stu1.age << "name=" << stu1.name; // age= 20 name= lili
37 } 

如此便可以发送一个带结构体的信号了.

注意,如果您打算在队列信号和槽连接或 QObject 的属性系统中使用该类型(QVariant),您还必须调用qRegisterMetaType(),因为名称是在运行时解析的。即当涉及到跨线程连接时,在 connect 之前需要调用qRegisterMetaType()注册此结构体;就像这样使用:

qRegisterMetaType<SRT_STUDENT>("SRT_STUDENT");    
connect(this,SIGNAL(sig_StudentInfo(QVariant)),this,SLOT(receiveSig(QVariant)));

问题:为什么自定义类型信号槽在跨线程会报错?

因为跨线程时,当发送方信号发出时,此时接受对象所在的线程未取得控制权,所以需要发送方需要将信号放在信号队列中储存发送的参数,QT就会去构造对象,而我们定义的是自定义类型,所以需要使用qRegisterMetaType()来注册,告诉QT怎么去构造对象.