qt 信号发射结构体
引用: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怎么去构造对象.