Qt线程间传递数据
因为Qt拥有信号与槽机制,所以线程间传递数据尤为方便
开始前的几点注意
1.槽参数必须是Qt内置的元数据类型,例如 int ,double,QString 等。
2.如果是自定义数据类型,必须在connect之前(qRegisterMetaType)注册成Qt的元数据。
3.线程间传递参数时,最好在参数前加上const限定符,加上const后,参数的生命周期会和程序的生命周期一样长,避免参数传递过程中,参数已到生命期而失效。
private:
readdata(const QString data);
readdata1(const ThreadCommunicate::mydata);
实例:
子线程与主线程传递元数据(QString)
client.h:
#ifndef CLIENT_H
#define CLIENT_H
#pragma execution_character_set("utf-8")
#include <QMainWindow>
#include <QThread>
#include <QUdpSocket>
#include <QHostAddress>
#include "threadcommunicate.h"
namespace Ui {
class Client;
}
class Client : public QMainWindow
{
Q_OBJECT
public:
explicit Client(QWidget *parent = nullptr);
~Client();
struct mydata{
QString info;
int flag;
};
private slots:
void on_pushButton_send_clicked();
void readData();
void on_pushButton_init_clicked();
void on_pushButton_thread_clicked();
void readdata(const QString data);
void on_pushButton_thread_2_clicked();
void readdata1(const ThreadCommunicate::mydata);
signals:
void sendsignal(); //发送信号给子线程,要求发送string字符串传过来
void sendsignal1(); //发送信号给子线程,要求发送自定义数据过来
private:
Ui::Client *ui;
QThread *subthread;
QUdpSocket *udp;
ThreadCommunicate *tc;
};
#endif // CLIENT_H
client.cpp:
#include "client.h"
#include "ui_client.h"
Client::Client(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Client)
{
ui->setupUi(this);
tc = new ThreadCommunicate();
QThread *thread = new QThread();
tc->moveToThread(thread);
thread->start();
connect(this, &Client::sendsignal, tc, &ThreadCommunicate::senddata);
connect(tc, &ThreadCommunicate::sendData, this, &Client::readdata);
qRegisterMetaType<mydata>("mydata");
connect(this, &Client::sendsignal1, tc, &ThreadCommunicate::senddata1);
connect(tc, &ThreadCommunicate::sendData1, this, &Client::readdata1);
}
Client::~Client()
{
delete ui;
}
void Client::on_pushButton_send_clicked()
{
for(ushort port=6666; port<6670; port++){
udp->writeDatagram(ui->textEdit_send->toPlainText().toUtf8(), QHostAddress("127.0.0.1"), port);
}
}
void Client::readData()
{
qDebug()<<"有节点发来消息";
QByteArray data;
data.resize(int(udp->pendingDatagramSize()));
qint64 len = udp->readDatagram(data.data(), data.size());
qDebug()<<"len:"<<len;
QString message = data.data();
if(len != -1 || len != 0){
ui->textEdit_receive->append(message);
}
qDebug()<<"message:"<<message;
}
void Client::on_pushButton_init_clicked()
{
udp = new QUdpSocket();
ushort port = ui->lineEdit->text().toUShort();
udp->bind(QHostAddress::Any, port);
connect(udp, &QUdpSocket::readyRead, this, &Client::readData);
ui->pushButton_init->setEnabled(false);
qDebug()<<port;
}
void Client::on_pushButton_thread_clicked()
{
emit sendsignal();
}
void Client::readdata(const QString data)
{
ui->textEdit_thread->append(data);
}
void Client::on_pushButton_thread_2_clicked()
{
emit sendsignal1();
}
void Client::readdata1(const ThreadCommunicate::mydata md)
{
ui->textEdit_thread_2->append(QString::number(md.flag)+" "+md.info);
}
ThreadCommunicate.h:
#ifndef THREADCOMMUNICATE_H
#define THREADCOMMUNICATE_H
#pragma execution_character_set("utf-8")
#include <QObject>
#include <QThread>
class ThreadCommunicate : public QObject
{
Q_OBJECT
public:
ThreadCommunicate(QObject *parent = nullptr);
struct mydata{
QString info;
int flag;
};
public slots:
void senddata();
void senddata1();
signals:
void sendData(const QString data); //发送字符串给主线程
void sendData1(const ThreadCommunicate::mydata); //发送自定义数据给主线程
};
#endif // THREADCOMMUNICATE_H
ThreadCommunicate.cpp:
#include "threadcommunicate.h"
ThreadCommunicate::ThreadCommunicate(QObject *parent) : QObject (parent)
{
qRegisterMetaType<ThreadCommunicate::mydata>("ThreadCommunicate::mydata");
}
void ThreadCommunicate::senddata()
{
int i = 0;
while(i<100){
QThread::sleep(1);
i++;
QString data = "线程通信样例" + QString::number(i);
emit sendData(data);
}
}
void ThreadCommunicate::senddata1()
{
int i = 0;
while(i<100)
{
QThread::sleep(1);
i++;
mydata md;
md.info = "我爱写程序";
md.flag = i;
emit sendData1(md);
}
}
main.cpp:
#include "client.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Client *w1 = new Client();
w1->show();
Client *w2 = new Client();
w2->show();
Client *w3 = new Client();
w3->show();
Client *w4 = new Client();
w4->show();
return a.exec();
}
client.ui:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Client</class>
<widget class="QMainWindow" name="Client">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1057</width>
<height>581</height>
</rect>
</property>
<property name="windowTitle">
<string>Client</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QGroupBox" name="groupBox">
<property name="geometry">
<rect>
<x>30</x>
<y>20</y>
<width>501</width>
<height>411</height>
</rect>
</property>
<property name="title">
<string>UDP通信</string>
</property>
<widget class="QTextEdit" name="textEdit_receive">
<property name="geometry">
<rect>
<x>10</x>
<y>80</y>
<width>481</width>
<height>191</height>
</rect>
</property>
</widget>
<widget class="QTextEdit" name="textEdit_send">
<property name="geometry">
<rect>
<x>10</x>
<y>280</y>
<width>381</width>
<height>111</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="pushButton_send">
<property name="geometry">
<rect>
<x>410</x>
<y>310</y>
<width>80</width>
<height>61</height>
</rect>
</property>
<property name="text">
<string>发送</string>
</property>
</widget>
<widget class="QLineEdit" name="lineEdit">
<property name="geometry">
<rect>
<x>10</x>
<y>30</y>
<width>151</width>
<height>41</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="pushButton_init">
<property name="geometry">
<rect>
<x>210</x>
<y>27</y>
<width>81</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>初始化</string>
</property>
</widget>
</widget>
<widget class="QGroupBox" name="groupBox_2">
<property name="geometry">
<rect>
<x>550</x>
<y>20</y>
<width>491</width>
<height>411</height>
</rect>
</property>
<property name="title">
<string>线程通信</string>
</property>
<widget class="QTextEdit" name="textEdit_thread">
<property name="geometry">
<rect>
<x>20</x>
<y>40</y>
<width>221</width>
<height>271</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="pushButton_thread">
<property name="geometry">
<rect>
<x>60</x>
<y>340</y>
<width>121</width>
<height>51</height>
</rect>
</property>
<property name="text">
<string>qt内嵌数据开始</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton_thread_2">
<property name="geometry">
<rect>
<x>310</x>
<y>340</y>
<width>121</width>
<height>51</height>
</rect>
</property>
<property name="text">
<string>自定义数据开始</string>
</property>
</widget>
<widget class="QTextEdit" name="textEdit_thread_2">
<property name="geometry">
<rect>
<x>260</x>
<y>40</y>
<width>221</width>
<height>271</height>
</rect>
</property>
</widget>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1057</width>
<height>19</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
结果截图: