Qt 线程通信 自定义数据

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>

结果截图:

猜你喜欢

转载自blog.csdn.net/wxy_csdn_world/article/details/104475069