QT 子线程 更改UI

一、问题原因:

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 
#include "HMyTcpClient.h"
#include 
#include 
#include 

#include 
#include 
#include 
#include 
#include 
#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 
#include 
 
#include 
#include 
#include 

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 
#include "HMyTcpSocket.h"
#include 
#include 
#include 
#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 
#include 
#include 

#include 

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();
}

你可能感兴趣的:(QT,qt)