继承QThread,QFuture和QtConcurrent,moveToThread(信号或invokeMethod使用)来使用线程

主要工程代码如下:

dialog.h:

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include "thread.h"
#include <QCloseEvent>

#include <QFuture>
#include <QFutureWatcher>
#include <QtConcurrent/QtConcurrent>

#include "pushbutton_d_thread.h"

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

    static Dialog* instance();

signals:
    void startThread_D();

private slots:
    void on_pushButton_clicked();           //A按钮,通过继承QThread的方式开启线程

    void on_pushButton_2_clicked();         //B按钮,通过继承QThread的方式开启线程

    void on_pushButton_3_clicked();         //Q按钮,退出按钮

    void on_pushButton_4_clicked();         //底部的打开文本按钮

    void on_pushButton_5_clicked();         //C按钮,通过QFuture和QtConcurrent和QFutureWatcher的方式开启线程

    /*
     * 1.主线程中开启子线程,然后在子线程里发信号改变主线程的E按钮文字信息
     * 2.通过invokeMethod函数,不用发信号的方式来从子线程直接改变主线程的E按钮文字信息
     */
    void on_pushButton_D_clicked();         //D按钮,通过moveToThread的方式开启线程

    void on_pushButton_E_clicked();         //D按钮,无作用,显示文本

    void on_changeUI_slot(QString str);

private:
    void closeEvent(QCloseEvent* event);

private:
    Ui::Dialog *ui;

    threadTest threadA;
    threadTest threadB;

    bool b_finish = false;
    QFuture<int> future;
    QFutureWatcher<int>* watcher = nullptr;

    QThread *m_threadD = nullptr;
    pushButton_DE_thread* pushButton_thread = nullptr;
};

#endif // DIALOG_H

dialog.cpp:

#include "dialog.h"
#include "ui_dialog.h"

#include <QFileDialog>
#include <QMessageBox>
#include <QTextCodec>
#include <QDebug>

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

    threadA.setMessage("A");
    threadB.setMessage("B");

    ui->pushButton->setText(QString::fromLocal8Bit("开始A"));
    ui->pushButton_2->setText(QString::fromLocal8Bit("开始B"));
    ui->pushButton_4->setText(QString::fromLocal8Bit("开始C"));
    ui->pushButton_3->setText(QString::fromLocal8Bit("退出"));
}

Dialog::~Dialog()
{
    if(threadA.isRunning())
        threadA.stop();

    if(threadB.isRunning())
        threadB.stop();

    if(watcher != nullptr && watcher->future().isRunning())
    {
        b_finish = true;
        watcher->future().waitForFinished();
        watcher = nullptr;
    }

    delete ui;
}

Dialog *Dialog::instance()
{
    static Dialog m_Instance;
    return &m_Instance;
}

void Dialog::on_pushButton_clicked()
{
    if(threadA.isRunning())
    {
        threadA.stop();
        ui->pushButton->setText(QString::fromLocal8Bit("线程A已启动"));
    }
    else
    {
        threadA.start();
        ui->pushButton->setText(QString::fromLocal8Bit("线程A已停止"));
    }
}

void Dialog::on_pushButton_2_clicked()
{
    if(threadB.isRunning())
    {
        threadB.stop();
        ui->pushButton_2->setText(QString::fromLocal8Bit("线程B已启动"));
    }
    else
    {
        threadB.start();
        ui->pushButton_2->setText(QString::fromLocal8Bit("线程B已停止"));
    }
}

void Dialog::on_pushButton_5_clicked()
{
    if(watcher == nullptr)
    {
        b_finish = false;
        //监控线程结束的信号
        watcher = new QFutureWatcher<int>;
        connect(watcher, &QFutureWatcher<int>::finished,[=](){

            ui->textEdit->setText(QString::fromLocal8Bit("线程C结束"));
            ui->pushButton_5->setText(QString::fromLocal8Bit("停止C"));

            watcher->deleteLater();
        });

        //开启新线程
        future = QtConcurrent::run([=](){

            for(int i=0;i<20;i++)
            {
                _sleep(1000);
                qDebug() << "C";
                qDebug() << "C1";
                if(b_finish)
                    break;
            }

            return 0;
        });

        ui->pushButton_5->setText(QString::fromLocal8Bit("线程C已启动"));
        watcher->setFuture(future);
    }
    else if(watcher != nullptr && watcher->future().isRunning())
    {
        b_finish = true;
        watcher->future().waitForFinished();
        watcher = nullptr;
        ui->pushButton_5->setText(QString::fromLocal8Bit("线程C已停止"));
    }
}

void Dialog::on_pushButton_3_clicked()
{
    this->close();
}

void Dialog::closeEvent(QCloseEvent *event)
{
    threadA.stop();
    threadB.stop();
    threadA.wait();
    threadB.wait();
    event->accept();
}

void Dialog::on_pushButton_4_clicked()
{
    QString sFilePath = QFileDialog::getOpenFileName(nullptr,QString::fromLocal8Bit("打开"),"","txt File(*.txt)");
    if(!sFilePath.isEmpty())
    {
        QFile file(sFilePath);
        if(!file.open(QIODevice::ReadOnly|QIODevice::Text))
        {
            QMessageBox::information(this,QString::fromLocal8Bit("提示"),QString::fromLocal8Bit("文件打开失败"));
            return;
        }

        QByteArray array;
        QTextCodec* codec = QTextCodec::codecForName("GBK");    //字段 别名为中文
        while(!file.atEnd())
        {
            QByteArray line = file.readLine();
            QString linestr = codec->toUnicode(line).trimmed();

            array += linestr;
        }

        ui->textEdit->setText(array);
        file.close();
    }
}

void Dialog::on_pushButton_D_clicked()
{
    if(m_threadD != nullptr && m_threadD->isRunning())
        m_threadD->quit();

    m_threadD = new QThread();
    pushButton_thread = new pushButton_DE_thread(this);
    pushButton_thread->moveToThread(m_threadD);

    connect(this,&Dialog::startThread_D,pushButton_thread,&pushButton_DE_thread::on_operationD_slot);
    connect(pushButton_thread,&pushButton_DE_thread::sig_changeOtherUI,this,&Dialog::on_changeUI_slot);
    connect(m_threadD,&QThread::finished,pushButton_thread,&QObject::deleteLater);

    connect(m_threadD,&QThread::finished,[=](){
        qDebug() << QString::fromLocal8Bit("线程pushButton_D_thread结束了");
    });

    m_threadD->start();
    emit startThread_D();
}

void Dialog::on_pushButton_E_clicked()
{
    ui->pushButton_E->setText("E");
}

void Dialog::on_changeUI_slot(QString str)
{
    ui->pushButton_E->setText(QString::fromLocal8Bit("D按钮子线程改变了E按钮%1").arg(str));
}

thread.h:

#ifndef THREAD_H
#define THREAD_H
#include <QThread>
#include <QtCore>
#include <QObject>
#include <QMutex>
#include <iostream>

using namespace std;

class threadTest : public QThread
{
public:
    void thread();

    void setMessage(const QString &message);
    void stop();

private slots:
    void run();

private:
    QString messageStr;

    volatile bool stopped = false;
    QMutex mtex;
};

#endif // THREAD_H

thread.cpp:

#include "thread.h"

void threadTest::thread()
{
    stopped = false;
}

void threadTest::setMessage(const QString &message)
{
    messageStr = message;
}

void threadTest::stop()
{
    stopped = true;
}

void threadTest::run()
{
    while(!stopped)
    {
        mtex.lock();
        _sleep(1000);
        qDebug() << messageStr;
        mtex.unlock();
    }
    stopped = false;
    std::cerr<<std::endl;
}

pushbutton_d_thread.h:

#ifndef PUSHBUTTON_D_THREAD_H
#define PUSHBUTTON_D_THREAD_H

#include <QObject>

class pushButton_DE_thread : public QObject
{
    Q_OBJECT
public:
    explicit pushButton_DE_thread(QObject *parent = 0);

    ~pushButton_DE_thread();

signals:
    void sig_changeOtherUI(QString);

public slots:
    void on_operationD_slot();

private:
    QMutex m_mutex;

    QObject* obj;
};

#endif // PUSHBUTTON_D_THREAD_H

pushbutton_d_thread.cpp:

#include "pushbutton_d_thread.h"

#include <QThread>
#include <QDebug>
#include "dialog.h"

pushButton_DE_thread::pushButton_DE_thread(QObject *parent) : QObject(parent)
  ,obj(parent)        //将父类指针传过来
{

}

pushButton_DE_thread::~pushButton_DE_thread()
{
}

void pushButton_DE_thread::on_operationD_slot()
{
    //主线程中开启子线程,然后在子线程里发信号改变主线程的E按钮文字信息
    if(0)
    {
        m_mutex.lock();
        qDebug() << "\n" << "-------------------------------------------";
        qDebug() << this->thread()->currentThreadId();
        qDebug() << QString::fromLocal8Bit("线程pushButton_D_thread开启了");
        QThread::sleep(3);
        qDebug() << "three hours later";
        qDebug() << "-------------------------------------------";

        emit sig_changeOtherUI(QString::fromLocal8Bit("(穿山甲:TNND,喝,为什么不喝~)"));
        m_mutex.unlock();
    }

    //通过invokeMethod函数,不用发信号的方式来从子线程直接改变主线程的E按钮文字信息
    if(1)
    {
        qDebug() << "\n" << "-------------------------------------------";
        qDebug() << this->thread()->currentThreadId();
        qDebug() << QString::fromLocal8Bit("线程pushButton_D_thread开启了");
        QThread::sleep(3);
        qDebug() << "three hours later";
        qDebug() << "-------------------------------------------";

        QString str = QString::fromLocal8Bit("(催逝员:我的任务完成了~)");
        QMetaObject::invokeMethod(obj,"on_changeUI_slot",Qt::QueuedConnection,Q_ARG(QString,str));
    }
}

UI设计界面如下:

工程代码:

链接: https://pan.baidu.com/s/1h3FGUdnTogYuKpTuWjgO2g?pwd=n22i 提取码: n22i

说一千遍爱你 这都不是问题
我用音乐来治你的公主病
《公主病》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值