目录
官方介绍
调用这个函数去注册类型T,这个T要使用Q_DECLARE_METATYPE()进行声明,返回meta type id,如下:
int id = qRegisterMetaType<MyStruct>();
这个函数需要他在被调用时有完整的定义。如果是指针类型他需要有完整的定义。使用Q_DECLARE_OPAQUE_POINTER()去注册指针用于转发数据类型。
使用Q_DECLARE_METATYPE()可以让这个数据类型T放到QVariant里面。如果想以队列的方式让T使用信号与槽,当第一次连接的时候就要调用qRegisterMetaType<T>()。
QObject::property()要和类型T一起使用,这个时候qRegisterMetaType<T>()要提前调用。通常把这个函数放到类型T的构造函数里面,或者main函数里面进行调用。
注意:这个函数是线程安全的
博主栗子
程序运行截图如下:
源码如下:
myworker.h
#ifndef MYWORKER_H
#define MYWORKER_H
#include <QThread>
struct MyData{
QString str;
};
Q_DECLARE_METATYPE(MyData)
class MyWorker : public QThread
{
Q_OBJECT
public:
explicit MyWorker(QObject *parent = 0);
void create(int time);
void destroy();
signals:
void sendMeg(MyData mydata);
private:
void run();
int m_time;
bool exitStatus;
};
#endif // MYWORKER_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "myworker.h"
class MyData;
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
protected:
void closeEvent(QCloseEvent *event)Q_DECL_OVERRIDE;
signals:
sendData(MyData *data);
public slots:
void receiveData(MyData mydata);
void exitThread();
private:
Ui::Widget *ui;
MyWorker m_myWorker[5];
};
#endif // WIDGET_H
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
myworker.cpp
#include "myworker.h"
#include <QVariant>
#include <QDebug>
MyWorker::MyWorker(QObject *parent) : QThread(parent)
{
qRegisterMetaType<MyData>();
exitStatus=false;
}
void MyWorker::create(int time)
{
m_time=time;
start();
}
void MyWorker::destroy()
{
exitStatus=true;
}
void MyWorker::run()
{
while(true&&!exitStatus){
MyData myData;
myData.str="currentThreadID:"+QString::number((unsigned int)QThread::currentThreadId())+" address 0x:"+QString::number((unsigned int)this,16);
QThread::msleep(m_time);
emit sendMeg(myData);
}
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QEventLoop>
#include <QTimer>
#include <QCloseEvent>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
for(int i=0;i<5;i++){
m_myWorker[i].create(1000+1*1000);
connect(&m_myWorker[i],SIGNAL(sendMeg(MyData)),this,SLOT(receiveData(MyData)),Qt::QueuedConnection); //多线程中默认也是Qt::QueuedConnection
}
}
Widget::~Widget()
{
delete ui;
}
void Widget::closeEvent(QCloseEvent *event)
{
QEventLoop loop;
QTimer::singleShot(100,this,SLOT(exitThread()));
QTimer::singleShot(1000*2,this,SLOT(close()));
QTimer::singleShot(1.5*1000,&loop,SLOT(quit()));
loop.exec();
event->accept();
}
void Widget::receiveData(MyData mydata)
{
ui->listWidget->insertItem(0,mydata.str);
}
void Widget::exitThread()
{
for(int i=0;i<5;i++){
m_myWorker[i].destroy();
}
}