主要工程代码如下:
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