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