Qt多个线程同时读取文件

通过实现两个线程同时按指定顺序读取图片,并显示在label中来了解Qt多线程QThread的使用(为方便实现,所使用的图片以1-10的数字命名)

一、线程类QThread的重载
1:mythread.h文件
定义的线程类命名为myThread,变量threadID用来确顶是哪一个线程发出信号;在函数threadBegin(),threadPause()和threadStop()中通过该改变bool类型变量pause和stop的值来达到控制线程启动、暂停、停止的目的。

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QObject>
#include <QThread>


class myThread :public QThread
{
Q_OBJECT
public:
    myThread();

    void threadBegin();//开始线程
    void threadPause();//暂停
    void threadStop();//终止
    void setThreadID(int id);

private:
    int p_seq;//图片序号
    bool pause=false;//暂停
    bool stop=false;//停止

    int threadID;//线程id

signals:
    //通过信号发出消息
    void pictureNumber(int p_seq,int threadID);

protected:
    void run();
};

#endif // MYTHREAD_H

2:mythread.cpp文件
通过重载QThread类中的虚函数run()来实现线程的主要任务,run()函数一般都是事件循环过程。通过发射信号来传递数据。信号pictureNumber(int,int)的两个参数分别是图片序号和线程id用于主线程中显示图片和确认线程。setThreadID(int id)用于赋予线程id。

#include "mythread.h"

myThread::myThread()
{
}

void myThread::setThreadID(int id)
{
    threadID=id;
}

void myThread::threadBegin()
{
    stop=false;
    pause=false;
}

void myThread::threadPause()
{
    if(pause)
        pause=false;
    else
        pause=true;
}

void myThread::threadStop()
{
    stop=true;
    p_seq=0;//线程终止后图片序号归为0
}


void myThread::run()
{//线程任务
    stop=false;
    p_seq=0;//线程启动时图片序号为0
    while(!stop)
    {
        if(!pause)
        {
            if(p_seq>=10)
            {
              p_seq=0;
            }
            emit pictureNumber(p_seq,threadID);//发射信号
            p_seq++;
        }
        msleep(500);
    }
    quit();//退出线程事件循环
}

二、主线程设计
1:主线程的界面布局
QLabel的变量label和label_2分别用于两个线程显示图片,三个QPushButton分别用于控制线程。
在这里插入图片描述
2:widget,h
槽函数getPicture(int num,int threadID)用于接收线程发出的信号,
#define threadNum 2表示使用的子线程数量为2(可根据需求自行定义)
重载closeEvent()事件,在关闭窗口时确保所有线程被停止

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QPixmap>
#include <QCloseEvent>
#include "mythread.h"
#define threadNum 2//子线程数量
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
    Q_OBJECT
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

protected:
    void closeEvent(QCloseEvent *event);
private slots:
    void on_pBStart_clicked();//线程开始

    void on_pBPause_clicked();//线程暂停

    void on_pBEnd_clicked();//线程结束
    
private slots:
    void getPicture(int num,int threadID);//线程信号槽函数

private:
   myThread thread[threadNum];//线程
private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

3:widget.cpp
子线程的id设置和线程信号和槽函数的连接都在构造函数中完成。

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    ui->pBStart->setEnabled(true);
    ui->pBPause->setEnabled(false);
    ui->pBEnd->setEnabled(false);

    ui->label->setScaledContents(true);
    ui->label_2->setScaledContents(true);

    //
    for(int i=0;i<threadNum;i++)
    {
        thread[i].setThreadID(i);//
        connect(&thread[i],SIGNAL(pictureNumber(int,int)),this,SLOT(getPicture(int ,int)));
    }
}

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


void Widget::getPicture(int num,int threadID)
{//线程信号响应的槽函数
    QPixmap temp;
    QString path=QString("pictures/%1.png").arg(num+1);
    temp.load(path);
    if(threadID==0)
       ui->label->setPixmap(temp);
    if(threadID==1)
       ui->label_2->setPixmap(temp);
}

void Widget::on_pBStart_clicked()
{//线程开始
    qDebug()<<"the begin";
    for(int i=0;i<threadNum;i++)
    {
        thread[i].start();
        thread[i].threadBegin();
    }
    ui->pBStart->setEnabled(false);
    ui->pBPause->setEnabled(true);
    ui->pBEnd->setEnabled(true);
}

void Widget::on_pBPause_clicked()
{//线程暂停
    for(int i=0;i<threadNum;i++)
    {
        thread[i].threadPause();
    }
    QString text;
    if(ui->pBPause->text()==QString::fromLocal8Bit("暂停"))
        text=QString::fromLocal8Bit("继续");
   else if(ui->pBPause->text()==QString::fromLocal8Bit("继续"))
         text=QString::fromLocal8Bit("暂停");
    ui->pBPause->setText(text);
}

void Widget::on_pBEnd_clicked()
{//线程结束
    for(int i=0;i<threadNum;i++)
    {
        thread[i].threadStop();
    }
    ui->pBStart->setEnabled(true);
    ui->pBEnd->setEnabled(false);
    ui->pBPause->setEnabled(false);
    if(ui->pBPause->text()==QString::fromLocal8Bit("继续"))
            ui->pBPause->setText(QString::fromLocal8Bit("暂停"));
}

void Widget::closeEvent(QCloseEvent *event)
{//窗口关闭,必须结束所有线程
    for(int i=0;i<threadNum;i++)
    {
        thread[i].threadStop();
        if(thread[i].isRunning())
        {//结束所有线程
            thread[i].threadStop();
            thread[i].wait();
        }
    }
    event->accept();
}


三、效果展示

Widget 2023-03-07 16-45-48

Qt Creator 多线程读取文件到程序显示 利用QT Creator多任务取一个文档到程序里 为了防止直接读取文件里的内容太大而发生卡顿,于是多线程取将更高效的解决这个问题。 效果图如下: 其中pro文件无需改动,默认就好,头文件h里面的内容为 #ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include #include QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MyObj; class MyObj : public QObject { Q_OBJECT public: MyObj(); //新的线程 signals: void toLine(QString line); private slots: void doWork(); }; class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private slots: void appendText(QString); //定义一个槽 private: Ui::MainWindow *ui; QThread *t; MyObj *obj; }; #endif // MAINWINDOW_H 而MAIN主文件的内容为了防止中文乱码做了如下修改: #include "mainwindow.h" #include #include int main(int argc, char *argv[]) { QApplication a(argc, argv); //设置中文字体 防止乱码 a.setFont(QFont("Microsoft Yahei", 9)); //设置中文编码 #if (QT_VERSION <= QT_VERSION_CHECK(5,0,0)) #if _MSC_VER QTextCodec *codec = QTextCodec::codecForName("GBK"); #else QTextCodec *codec = QTextCodec::codecForName("UTF-8"); #endif QTextCodec::setCodecForLocale(codec); QTextCodec::setCodecForCStrings(codec); QTextCodec::setCodecForTr(codec); #else QTextCodec *codec = QTextCodec::codecForName("UTF-8"); QTextCodec::setCodecForLocale(codec); #endif MainWindow w; w.show(); return a.exec(); } 接下来重点来了,源文件CPP里为 #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); t = new QThread(); //QThread obj = new MyObj(); obj->moveToThread(t); qDebug()<<"main thread:"<<QThread::currentThread(); connect(t,SIGNAL(started()), obj, SLOT(doWork())); connect(obj,SIGNAL
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zmq1998

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值