> 文章列表 > Qt使用std::thread更新QPlainTextEdit内容

Qt使用std::thread更新QPlainTextEdit内容

Qt使用std::thread更新QPlainTextEdit内容

Qt使用std::thread更新QPlainTextEdit内容

  • 一、演示
  • 二、部分代码讲解
    • 1. 启动函数
    • 2. 线程函数
  • 三、代码片段
    • 1. 主函数
    • 2. MainWindow.h
    • 3. MainWindow.cpp 源文件
  • 四、TCP相关解释


导言:记录Qt使用std::thread更新QPlainTextEdit内容

在写一个简易的服务端发送软件中,需要表示正在发送的内容是哪些,需要在QPlainText中去标记发送对应的内容。这个就应用而生。也是用的单例和 标准的 std::thread来驱动的。有些是没有做完的,下面是全部的开源代码。

一、演示

Qt使用std::thread更新QPlainTextEdit

二、部分代码讲解

1. 启动函数

下面就是整个函数线程的启动函数,因为用到了界面的一些东西,就需要注册一些 类型 ,也是分离运行的

void MainWindow::slotSendBtnClicked()
{ui->SendPlainText->clear();ui->SendPlainText->setPlainText(SendContent);MainWindow::Instance->ui->SendBtn->setEnabled(false);//注册类型qRegisterMetaType<QTextBlock>("QTextBlock");qRegisterMetaType<QTextDocument*>("QTextDocument*");qRegisterMetaType<QTextCursor>("QTextCursor");std::thread t_thread(MainWindow::SendThread, MainWindow::Instance->ui->SendPlainText->document());t_thread.detach();
}

2. 线程函数

这里使用的是静态的函数,数据刷新线程也是通过发送信号,通知主界面去更新内容的,也是用的信号槽机制。

void MainWindow::SendThread(QTextDocument *document)
{QTextCursor cursor( document);cursor.setPosition(0);for (int i = 0; i <MainWindow::Instance->SendContentList.length(); i++){//发送数据emit MainWindow::Instance->updateLogInfo(QString("已发送序号 %1: ").arg(i+1)+ MainWindow::Instance->SendContentList[i]);emit MainWindow::Instance->writeToSocket(MainWindow::Instance->SendContentList[i]);cursor.insertText(">>> ");cursor.movePosition(QTextCursor::StartOfLine);cursor.movePosition(QTextCursor::Down);MainWindow::Instance->ui->SendPlainText->verticalScrollBar()->setValue(cursor.blockNumber() - 5);_sleep(MainWindow::Instance->ui->comboBox->currentText().toDouble() * 1000);}MainWindow::Instance->ui->SendBtn->setEnabled(true);MainWindow::Instance->ui->SendBtn->setText("再次发送");
}

三、代码片段

1. 主函数

主函数这里设置了使用 Fusion 风格的窗口

#include "MainWindow.h"#include <QApplication>
#include <QStyleFactory>int main(int argc, char *argv[])
{QApplication a(argc, argv);qApp->setStyle(QStyleFactory::create(QStringLiteral("Fusion")));MainWindow *w = MainWindow::GetInstance();w->show();return a.exec();
}

2. MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
#include <QFileDialog>
#include <QFile>
#include <QTextStream>
#include <QProcess>
#include <QUrl>
#include <QDesktopServices>
#include <thread>
#include <QTextDocument>
#include <QScrollBar>
#include <QTextBlock>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QWidget
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();static MainWindow* GetInstance();signals://打印日志void updateLogInfo(QString info);//向socket写数据void writeToSocket(QString data);
private slots://处理新连接void slotNewConnect();//处理接收void slotReadyRecv();//处理发送void slotReadySend();//处理连接关闭void slotDisconnect();//启动监听void slotListenPort();private slots://选择文件发送void slotOpenFileBtnClicked();//当文件路径按钮被点击的时候void on_pushButton_clicked();//当发送按钮点击时void slotSendBtnClicked();//设置提示函数void slotUpdateInfo(QString info);//处理接收写socket信号函数void slotWriteToSocket(QString data);void on_pushButton_2_clicked();void on_pushButton_3_clicked();void on_pushButton_4_clicked();void on_pushButton_5_clicked();void on_OnTopCheck_stateChanged(int arg1);void on_OnTopCheck_toggled(bool checked);private:Ui::MainWindow *ui;QTcpServer * m_TcpSever;static MainWindow* Instance;//负责通信QTcpSocket *m_TcpSocket;//设置提示信息void OutPutInfo(QString info);//发送内容缓存QStringList SendContentList;//发送内容字符串QString SendContent;static void SendThread(QTextDocument *document);
};
#endif // MAINWINDOW_H

3. MainWindow.cpp 源文件

#include "MainWindow.h"
#include "ui_MainWindow.h"MainWindow * MainWindow::Instance = nullptr;MainWindow::MainWindow(QWidget *parent): QWidget(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);this->setWindowTitle("服务器数据程序");//创建对象m_TcpSever = new QTcpServer(this);//为sever绑定连接函数connect(m_TcpSever, &QTcpServer::newConnection, this, &MainWindow::slotNewConnect);//    connect(ui->SendBtn, &QPushButton::clicked, this, &MainWindow::slotReadySend);connect(ui->StartListenBtn, &QPushButton::clicked, this, &MainWindow::slotListenPort);connect(ui->openFileBtn, &QPushButton::clicked, this, &MainWindow::slotOpenFileBtnClicked);connect(ui->SendBtn, &QPushButton::clicked, this, &MainWindow::slotSendBtnClicked);connect(this, &MainWindow::updateLogInfo, this, &MainWindow::slotUpdateInfo);connect(this, &MainWindow::writeToSocket, this, &MainWindow::slotWriteToSocket);//触发置顶消息emit ui->OnTopCheck->toggled(true);
}MainWindow::~MainWindow()
{delete ui;
}MainWindow *MainWindow::GetInstance()
{if(Instance == nullptr){Instance = new MainWindow();}return Instance;
}void MainWindow::slotNewConnect()
{//处理客户端请求m_TcpSocket= m_TcpSever->nextPendingConnection();ui->ReceivePlainText->appendPlainText(QString("receive connect from IP: %1 Port: %2 ").arg(m_TcpSocket->peerName()).arg(m_TcpSocket->peerPort()));emit updateLogInfo(QString("接收到来自 IP: %1 端口: %2  的连接").arg(m_TcpSocket->peerName()).arg(m_TcpSocket->peerPort()));//初试连接发送数据m_TcpSocket->write("你好客户端!准备开始新的数据传输旅程吧!");//6.连接信号,接受客户端数据connect(m_TcpSocket, &QTcpSocket::readyRead, this, &MainWindow::slotReadyRecv);connect(m_TcpSocket, &QTcpSocket::disconnected, this, &MainWindow::slotDisconnect);
}void MainWindow::slotReadyRecv()
{QString data = QString::fromUtf8(m_TcpSocket->readAll());ui->ReceivePlainText->appendPlainText(data);ui->ReceivePlainText->appendPlainText("\\n-----------------");
}void MainWindow::slotReadySend()
{QString sendData = ui->SendPlainText->toPlainText();m_TcpSocket->write(sendData.toUtf8());
}void MainWindow::slotDisconnect()
{ui->ReceivePlainText->appendPlainText("Connect Finished!");emit updateLogInfo("连接结束!");
}void MainWindow::slotListenPort()
{m_TcpSever->listen(QHostAddress::Any, ui->PortComBox->currentText().toUInt());emit updateLogInfo("启动监听成功!");ui->StartListenBtn->setText("监听中");
}void MainWindow::slotOpenFileBtnClicked()
{QString fileName = QFileDialog::getOpenFileName( this, tr( "打开待发送数据" ), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), tr( "txt 文件 (*.txt)" ) );if ( !fileName.isNull() ){ui->SendPlainText->clear();SendContentList.clear();//设置ui->pushButton->setText( fileName );QFile file( fileName );if ( !file.open( QIODevice::ReadOnly | QIODevice::Text )){emit updateLogInfo("mcp 流程控制文件打开失败!" );return;}else{emit updateLogInfo("mcp 流程控制文件打开成功!" );}QTextStream outs( &file );outs.setCodec( "UTF-8" );ui->SendPlainText->insertPlainText(outs.readAll());SendContent = ui->SendPlainText->toPlainText();SendContentList = ui->SendPlainText->toPlainText().split('\\n');file.close();}
}void MainWindow::OutPutInfo(QString info)
{ui->RunTimeInfoInput->appendPlainText("[Info]: " + info);
}void MainWindow::SendThread(QTextDocument *document)
{QTextCursor cursor( document);cursor.setPosition(0);for (int i = 0; i <MainWindow::Instance->SendContentList.length(); i++){//发送数据emit MainWindow::Instance->updateLogInfo(QString("已发送序号 %1: ").arg(i+1)+ MainWindow::Instance->SendContentList[i]);emit MainWindow::Instance->writeToSocket(MainWindow::Instance->SendContentList[i]);cursor.insertText(">>> ");cursor.movePosition(QTextCursor::StartOfLine);cursor.movePosition(QTextCursor::Down);MainWindow::Instance->ui->SendPlainText->verticalScrollBar()->setValue(cursor.blockNumber() - 5);_sleep(MainWindow::Instance->ui->comboBox->currentText().toDouble() * 1000);}MainWindow::Instance->ui->SendBtn->setEnabled(true);MainWindow::Instance->ui->SendBtn->setText("再次发送");
}void MainWindow::on_pushButton_clicked()
{if(QDesktopServices::openUrl(QUrl::fromLocalFile(ui->pushButton->text()))){emit updateLogInfo("系统打开数据文件成功!");}else{emit updateLogInfo("系统打开数据文件失败!");}
}void MainWindow::slotSendBtnClicked()
{ui->SendPlainText->clear();ui->SendPlainText->setPlainText(SendContent);MainWindow::Instance->ui->SendBtn->setEnabled(false);qRegisterMetaType<QTextBlock>("QTextBlock");qRegisterMetaType<QTextDocument*>("QTextDocument*");qRegisterMetaType<QTextCursor>("QTextCursor");std::thread t_thread(MainWindow::SendThread, MainWindow::Instance->ui->SendPlainText->document());t_thread.detach();
}void MainWindow::slotUpdateInfo(QString info)
{OutPutInfo(info);
}void MainWindow::slotWriteToSocket(QString data)
{m_TcpSocket->write(data.toUtf8());
}void MainWindow::on_pushButton_2_clicked()
{QString fileName = QFileDialog::getOpenFileName( this, tr( "打开待发送数据" ), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), tr( "mcp 文件 (*.mcp)" ) );if ( !fileName.isNull() ){ui->ConfigFilePathLB->setText(fileName);OutPutInfo(fileName);}
}void MainWindow::on_pushButton_3_clicked()
{emit writeToSocket("MCP=" + ui->ConfigFilePathLB->text());
}void MainWindow::on_pushButton_4_clicked()
{emit writeToSocket("StartMeasure");
}void MainWindow::on_pushButton_5_clicked()
{emit writeToSocket("StopMeasure");
}void MainWindow::on_OnTopCheck_stateChanged(int arg1)
{}void MainWindow::on_OnTopCheck_toggled(bool checked)
{Qt::WindowFlags m_flags = windowFlags();if (checked){setWindowFlags(m_flags | Qt::WindowStaysOnTopHint);this->show();}else{setWindowFlags(NULL);this->show();}
}

四、TCP相关解释

这里就是当一个新的连接来了之后,处理的一些响应,我这里只做了一对一的连接通信,并没有考虑到具体向某一个 客户端通信,这里要注意一下。

void MainWindow::slotNewConnect()
{//处理客户端请求m_TcpSocket= m_TcpSever->nextPendingConnection();ui->ReceivePlainText->appendPlainText(QString("receive connect from IP: %1 Port: %2 ").arg(m_TcpSocket->peerName()).arg(m_TcpSocket->peerPort()));emit updateLogInfo(QString("接收到来自 IP: %1 端口: %2  的连接").arg(m_TcpSocket->peerName()).arg(m_TcpSocket->peerPort()));//初试连接发送数据m_TcpSocket->write("你好客户端!准备开始新的数据传输旅程吧!");//6.连接信号,接受客户端数据connect(m_TcpSocket, &QTcpSocket::readyRead, this, &MainWindow::slotReadyRecv);connect(m_TcpSocket, &QTcpSocket::disconnected, this, &MainWindow::slotDisconnect);
}

这里就是写入数据到socket里面的

void MainWindow::slotWriteToSocket(QString data)
{m_TcpSocket->write(data.toUtf8());
}