# Qt子线程读文件 **Repository Path**: ss103838/qt-sub-thread-reads-files ## Basic Information - **Project Name**: Qt子线程读文件 - **Description**: Qt使用子线程读文件 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2025-04-04 - **Last Updated**: 2025-10-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: Qt子线程 ## README Qt项目中,如遇到复杂的,耗时的任务,如果不经过子线程处理,会导致界面卡顿; 用子线程处理文件在项目中使用频率比较高,本案写一个简单的子线程处理文件的Demo; ![image-20250404142701854](README.assets/image-20250404142701854.png) 之所以说使用频繁,因为项目中大多对文件操作的项目还比较多,只要稍加修改即可应对大多数项目; 第一步: 界面布局 ![image-20250404142830265](README.assets/image-20250404142830265.png) 界面简单不做过多解释; ```xml  Widget              0     0     278     149              Widget                                                                             选择文件                                                             子线程遍历文件                         ``` 第二步: 先介绍重点: 在widget里面先创建建一个线程并开启 ![image-20250404142931778](README.assets/image-20250404142931778.png) ``` 以上有两个要点: 第一个: 线程要开启;否则对应的槽函数不会执行第二个:主界面一定要通过信号触发槽函数,否则还是主线程去执行文件遍历 ``` widget.h ```c++ #ifndef WIDGET_H #define WIDGET_H #include  #include  class ReadFile; QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACE class Widget : public QWidget {     Q_OBJECT public:     Widget(QWidget *parent = nullptr);     ~Widget(); private slots:     void on_threadBtn_clicked();     void on_selectBtn_clicked(); signals:     void readFileEmit(QString path); private:     Ui::Widget *ui;     QThread* thread;     ReadFile* readFile;     QProgressDialog progressDialog; }; #endif // WIDGET_H ``` widget.cpp ```c++ #include "widget.h" #include "ui_widget.h" #include "readfile.h" #include  #include  #include  #include  Widget::Widget(QWidget *parent)     : QWidget(parent)     , ui(new Ui::Widget)     ,thread(new QThread)     ,readFile(new ReadFile) {     ui->setupUi(this);     qDebug()<<"Widget threadId"<moveToThread(thread);     connect(this,&Widget::readFileEmit,readFile,&ReadFile::readFile);     progressDialog.setWindowTitle("任务进度");     progressDialog.setWindowModality(Qt::WindowModal); // 设置为模态对话框     // 调用reset函数,里面对定时器进行了stop,因此就不再会自动弹出     progressDialog.reset();     connect(readFile, &ReadFile::currentValue, &progressDialog, &QProgressDialog::setValue);     thread->start(); } Widget::~Widget() {     thread->quit();     thread->wait();     delete ui; } void Widget::on_threadBtn_clicked() {     emit readFileEmit(ui->filePath->text());     // 千万不能使用下面的调用方式,这样只会让主线程执行文件的遍历     // readFile->readFile(ui->filePath->text()); } void Widget::on_selectBtn_clicked() {     QString path = QFileDialog::getOpenFileName(nullptr,"Open Text File",QDir::homePath(),"Text Files (*.txt);;All Files(*)");     if(path.isEmpty())     {         QMessageBox::warning(this,"选择文件","选择的文件不能为空");         return;     }     ui->filePath->setText(path); } ``` ReadFile类中,读文件 ![image-20250404143006847](README.assets/image-20250404143006847.png) ReadFile.h ```c++ #ifndef READFILE_H #define READFILE_H #include  class ReadFile : public QObject {     Q_OBJECT public:     explicit ReadFile(QObject *parent = nullptr); public slots:     void readFile(QString path); signals:     void currentValue(int); }; #endif // READFILE_H ``` ReadFile.cpp ```c++ #include "readfile.h" #include  #include  #include  ReadFile::ReadFile(QObject *parent)     : QObject{parent} { } void ReadFile::readFile(QString path) {     qDebug()<<"ReadFile threadId"< int main(int argc, char *argv[]) {     QApplication a(argc, argv);     Widget w;     w.show();     return a.exec(); } ``` **总结:** 代码比较简单,但是有几个关键点 ``` 第一个: 线程一定要开启,否则槽函数不会执行; 第二个: 主界面一定要通过信号触发执行的槽函数,否则还是主线程去执行 第三点: 进度条默认会显示,因为进度条中有定时器,需要reset才不会显示 ``` ``` thread.start(); connect(this,&Widget::readFileEmit,readFile,&ReadFile::readFile); ```