1.1.传递复杂数据类型QT内部提供一组宏:
Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(Container)声明关联容器元类型
Q_DECLARE_METATYPE(Type) 声明元类型
Q_DECLARE_OPAQUE_POINTER(PointerType) 声明不透明的指针
Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(Container) 声明顺序容器元类型
Q_DECLARE_SMART_POINTER_METATYPE(SmartPointer) 智能指针
1.2.QT信号与槽连接方式:
1)Qt::AutoConnection
表示系统自动选择相应连接方式,如信号与槽在同一线程采用Qt::DirectConnection,
如信号与槽不在同一线程采用Qt::QueuedConnection的连接方式。
2)Qt::DirectConnection
表示一旦信号产生立即执行槽函数
3)Qt::QueuedConnection
表示信号产生后,将发送Event给你receiver所在线程postEvent(QEvent::MetaCall,...),
slot函数会在receiver所在线程的event loop中进行处理
4)Qt::BlockingQueuedConnection
表示信号产生后调用sendEvent(QEvent::MetaCall,...),
在receiver所在的线程处理完成后才会返回;只能当sender,receiver不在同一线程时才可以
5)Qt::UniqueConnection
表示只有它不是一个重复连接,连接才会成功。
如果之前已经有了一个链接(相同信号连接到同一对象的同一个槽上),那么连接将会失败并将返回false
6)Qt::AutoCompatConnection与QT3保持兼容性
说明:
1)对于任何QThread来说,其线程只存在于run()函数内,其它函数都不在线程内
2)SOCKET采用Qt::BlockingQueuedConnection,当SOCKET有数据到达时就会发出readyRead()信号,
此时可能之前receiveFile()还未执行完,用Qt::AutoConnection传输大文件时就会出错,
原因在于只要有数据到达时就会连接信号但数据接收还没处理完毕,
Qt::BlockingQueuedConnection会阻塞此连接,直到receiveFile()处理完毕并返回后才发送信号
qDebug()<<"run thread:"<<QThread::currentThreadId();
connect(tcpSocket,SIGNAL(readyRead()),this,SIGNAL(receiveSgl(tcpSocket)));
connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(receiveFile()),Qt::BlockingQueuedConnection);
exec();
1.3.Qt线程间共享数据
说明:Qt本身类型直接传送。如自定义类型想用signal/slot不能直接使用
步骤:
1)定义数据类型:typedef unsigned short u16;//或类结构体
2)声明数据类型:Q_DECLARE_METATYPE(u16) //在定义数据类型文件中声明
3)注册数据类型:构造函数(也可在mian.cpp中)
qRegisterMetaType<u16>("u16")
qRegisterMetaType(u16*)("u16*"); //指针
qRegisterMetaType(u16*)("u16&"); //引用
4)信号槽关联:
connect(...) //构造函数(也可在mian.cpp中)
2. 示例:
//U16.h
#pragma once
#include <QMetatype>
typedef unsigned short U16;
Q_DECLARE_METATYPE(U16);
//MyThread.h
#pragma once
#include <QThread>
#include "U16.h"
class MyThread :public QThread{
Q_OBJECT
public:
MyThread(QObject *parent = Q_NULLPTR);
~MyThread() { delete m_x3; }
void set_data(U16 x1, U16 &x2,U16* x3);
public:
void run();
signals:
void thread_signal(U16 x1, U16 &x2, U16* x3);
public slots:
void get_thread_signal(U16 x1, U16 &x2, U16* x3);
private:
U16 m_x1=0,_m_x2=0;
U16 &m_x2= _m_x2;
U16 *m_x3=nullptr;
};
//MyThread.cpp
#include "MyThread.h"
#include <iostream>
MyThread::MyThread(QObject *parent) : QThread(parent) {
if (m_x3 == nullptr) m_x3 = new U16(0);
connect(this, &MyThread::thread_signal, this, &MyThread::get_thread_signal, Qt::DirectConnection);
}
void MyThread::run() {
set_data(m_x1, m_x2,m_x3);
emit thread_signal(m_x1, m_x2,m_x3);
}
void MyThread::set_data(U16 x1, U16 &x2, U16* x3) { m_x1 = x1; m_x2 = x2;* m_x3 = *x3; }
void MyThread::get_thread_signal(U16 x1, U16 &x2, U16* x3) {
std::cout << x1 <<";"<< x2 << ";" <<*x3<< std::endl;
}
//MyObject.h
#pragma once
#include <QObject>
#include "u16.h"
#include <iostream>
#include "MyThread.h"
class MyObject :public QObject{
Q_OBJECT
public:
explicit MyObject(MyThread *thread=nullptr,QObject *parent = Q_NULLPTR);
~MyObject() { }
void get_thread_signal(U16 x1, U16 &x2, U16* x3);
private:
MyThread *mythread=nullptr;
};
//MyObject.cpp
#include "MyObject.h"
#include <QMetatype>
MyObject::MyObject(MyThread *thread,QObject *parent) :QObject(parent) {
qRegisterMetaType<U16>("U16");
qRegisterMetaType<U16*>("U16&");
qRegisterMetaType<U16*>("U16*");
mythread = thread;
connect(mythread, &MyThread::thread_signal, this, &MyObject::get_thread_signal);
//connect(mythread, &MyThread::finished, this, &QObject::deleteLater);
}
void MyObject::get_thread_signal(U16 x1, U16 &x2, U16* x3) {
std::cout << "x1=" << x1 << "; &x2=" << x2 << "; *x3=" << *x3 << std::endl;
}
//main.cpp
#include <QtCore/QCoreApplication>
#include <iostream>
#include "MyThread.h"
#include "MyObject.h"
int main(int argc, char *argv[]){
QCoreApplication a(argc, argv);
std::cout << "ready start thread..." << std::endl;
MyThread t; MyObject obj(&t);
U16 x1 = 1, x2 = 2,x3=3;
t.set_data(x1, x2,&x3);
t.start();
return a.exec();
}