0
点赞
收藏
分享

微信扫一扫

QT 子线程 更改UI

云竹文斋 2023-02-28 阅读 110


一、问题原因:

QT和Android类似,不能在子线程中直接更新UI,否则会有崩溃;

二、实现方式

方式有几种,我这里只说一种,使用 信号机制;

三、原理:

原理其实是信号槽机制,槽连接方式:

有以下四种,如果未设置默认 auto,即可跨线程通信;

Direction、queued、blockingqueued、unique、auto

链接方式

描述

自动

同线程同步,跨线程异步。(默认)如果信号的发送和接收方在相同线程的情况下,使用Qt::DirectConnection。否则,使用Qt::QueuedConnection。在发出信号时确定连接类型。

直连

同线程同步。当发出信号时,槽函数立即被调用。槽在发送信号的线程中执行。

队列

跨线程异步。当控制返回到接收方线程的事件循环时调用槽。槽在接收方的线程中执行。

阻塞队列

与Qt::QueuedConnection相同,只是发送信号的线程会阻塞,直到槽返回。如果接收方存在于发送信号的线程中,则不能使用此连接,否则应用程序将死锁。

唯一

防止重复链接,前四种是互斥的,这个跟前几个任意组合

四、实现步骤:

首先 MainWindow 声明,定义(UI 线程)

public  slots:
// 参数类型,注册最好不要自定义
void sltCallBackkSocketState(int state,QString socketInfo );

void MainWindow::sltCallBackkSocketState(int state,QString socketInfo )
{
//通过信号槽过来,可以直接修改UI
ui->label_connect_state->setText(socketInfo);
}

  MainWindow  中,通过connect 将 信号和槽连结起来

mWorker = new HMyTcpWorker(mSocketCallInterface,m_nHandle);
m_thread = new QThread(mWorker);
mWorker->moveToThread(m_thread);

connect(mWorker, SIGNAL(sigCallBackkSocketState(int,QString)),
this, SLOT(sltCallBackkSocketState(int,QString)));

子线程

signals:


void sigCallBackkSocketState(int state,QString socketInfo );

void HMyTcpWorker::onError(QAbstractSocket::SocketError)
{
QTcpSocket* sock = (QTcpSocket*)sender();

if(QAbstractSocket::ConnectedState != sock->state())
{
emit sigCallBackkSocketState(SOCKET_STATE_ERROR,sock->errorString());
}
qDebug() << "Socket error:" << sock->errorString();
}

以下是全部代码:

MainWindow  

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "HMyTcpClient.h"
#include <QtNetwork>
#include <QTcpSocket>
#include <QHostAddress>

#include <QDataStream>
#include <QByteArray>
#include <QDebug>
#include <QDateTime>
#include <QFile>
#include "HMyTcpWorker.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();



private:
Ui::MainWindow *ui;


public slots:
// 参数类型,注册最好不要自定义
void sltCallBackkSocketState(int state,QString socketInfo );



private:
HMyTcpWorker * mWorker;

};

#endif // MAINWINDOW_H

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QGridLayout>
#include <QDebug>

#include <qfiledialog.h>
#include <qfile.h>
#include <qstring.h>

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),

ui(new Ui::MainWindow)
{
ui->setupUi(this);


this->setWindowTitle("Client");
ui->mainToolBar->setVisible (false);//
ui->label_connect_state->setText("未连接");

mWorker = new HMyTcpWorker(mSocketCallInterface,m_nHandle);
m_thread = new QThread(mWorker);
mWorker->moveToThread(m_thread);

connect(mWorker, SIGNAL(sigCallBackkSocketState(int,QString)),
this, SLOT(sltCallBackkSocketState(int,QString)));


}

MainWindow::~MainWindow()
{
delete ui;
}

void MainWindow::sltCallBackkSocketState(int state,QString socketInfo )
{
ui->label_connect_state->setText(socketInfo);
}

HMyTcpWorker

#ifndef HMYTCPWORKER_H
#define HMYTCPWORKER_H

#include <QObject>
#include "HMyTcpSocket.h"
#include <QTcpSocket>
#include <QDateTime>
#include <QFile>
#include "socketcallinterface.h"

class HMyTcpWorker : public QObject
{
Q_OBJECT
public:
explicit HMyTcpWorker(qintptr socketHandle, QObject *parent = 0);
~HMyTcpWorker();



private:
HMyTcpSocket* m_tcpSocket;



signals:


void sigCallBackkSocketState(int state,QString socketInfo );

public slots:

void onConnect();


void onError(QAbstractSocket::SocketError);

private:


系统时间
QDateTime current_date_time;
QString str_date_time;
};

#endif // HMYTCPWORKER_H

#include "HMyTcpWorker.h"
#include <QDebug>
#include <QXmlStreamReader>
#include <QDataStream>

#include <QMessageBox>

HMyTcpWorker::HMyTcpWorker( qintptr socketHandle, QObject *parent)
: QObject(parent),
m_nID(socketHandle),
mSocketCallInterface(interface)
{
m_tcpSocket = NULL;

}

HMyTcpWorker::~HMyTcpWorker()
{
qDebug() << QString::fromLocal8Bit("析构……。……。……。……。……。……………。");
}



void HMyTcpWorker::sltConnectServer(QString hostName, int port, int timeout)
{
if(NULL == m_tcpSocket)
{
m_tcpSocket = new HMyTcpSocket(m_nID);

connect(m_tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(onError(QAbstractSocket::SocketError)));
connect(m_tcpSocket, SIGNAL(connected()), this, SLOT(onConnect()));


}

if(m_tcpSocket)
{
m_tcpSocket->connectToHost(hostName, port);
if(!m_tcpSocket->waitForConnected(timeout))
{
qDebug()<<"conncet to server is timeout";
emit sigResult(-1);
}
else
{
emit sigResult(0);
}
}
}


void HMyTcpWorker::onConnect()
{
qDebug() << "Connected!";
}

void HMyTcpWorker::onError(QAbstractSocket::SocketError)
{
QTcpSocket* sock = (QTcpSocket*)sender();

if(QAbstractSocket::ConnectedState != sock->state())
{
emit sigCallBackkSocketState(SOCKET_STATE_ERROR,sock->errorString());
}
qDebug() << "Socket error:" << sock->errorString();
}

举报

相关推荐

0 条评论