一、功能说明
1、通过继承QThread,重写run的方式实现多线程
2、点击“开始”按钮启动子线程,同时通过信号槽的方式给子线程发送“开始”字符串;
3、子线程每隔1秒向主线程发送累加数;
4、点击"停止"按钮,通过函数调用的方式停止子线程;
二、项目创建
1、新建Qt Widgets应用,名称为ThreadRun,基类选择QMainWindow;
2、MainWindow.ui中放入两个Push Button按钮,第一个text改为“开始”,objectNme改为startButton,第二个text改为“停止”,objectNme改为stopButton;
3、添加新的C++类,名称为MyThread,基类设置为QThread
三、代码演示
1、MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include "MyThread.h"namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = nullptr);~MainWindow();signals:void sendData(QString);private slots:void on_startButton_clicked();void on_stopButton_clicked();void doSendValue(int);private:Ui::MainWindow *ui;MyThread *m_myThread;
};#endif // MAINWINDOW_H
2、MainWindow.cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);qDebug() << "主线程id:" << QThread::currentThreadId();m_myThread = new MyThread(this);//接收子线程数据connect(m_myThread, &MyThread::sendValue, this, &MainWindow::doSendValue);//给子线程发送数据connect(this, &MainWindow::sendData, m_myThread, &MyThread::doSendData);ui->startButton->setEnabled(true);ui->stopButton->setEnabled(false);
}MainWindow::~MainWindow()
{if(m_myThread->isRunning()){m_myThread->stop();}m_myThread->quit(); //将子线程停止m_myThread->wait(); //等待子线程的运行结束后再停止delete ui;
}void MainWindow::on_startButton_clicked()
{emit sendData("开始");qDebug() << "主线程 startButtonid:" << QThread::currentThreadId();m_myThread->start(); //子线程开始,自动调用run()函数ui->startButton->setEnabled(false);ui->stopButton->setEnabled(true);
}void MainWindow::on_stopButton_clicked()
{qDebug() << "主线程 stopButtonid:" << QThread::currentThreadId();if(m_myThread->isRunning()){m_myThread->stop();ui->startButton->setEnabled(true);ui->stopButton->setEnabled(false);}}void MainWindow::doSendValue(int value)
{qDebug() << value << "doSendValue 线程id:"<< QThread::currentThreadId();
}
3、MyThread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H#include <QObject>
#include <QThread>
class MyThread : public QThread
{Q_OBJECT
public:explicit MyThread(QObject *parent = nullptr);public slots:void stop();void doSendData(QString);protected:void run();signals:void sendValue(int);private slots:void showValue();private:volatile bool stopped;int value;
};#endif // MYTHREAD_H
4、MyThread.cpp
#include "MyThread.h"
#include <QThread>
#include <QDebug>MyThread::MyThread(QObject *parent) : QThread (parent)
{stopped = false;qDebug() << "创建 子线程id:" << QThread::currentThreadId();
}void MyThread::stop()
{stopped = true;qDebug() << "stop 子线程id:" << QThread::currentThreadId();
}void MyThread::doSendData(QString str)
{qDebug() << str << "doSendData 子线程id:" << QThread::currentThreadId();
}void MyThread::run()
{value = 0;qDebug() << "run 子线程id:" << QThread::currentThreadId();while(!stopped){showValue();msleep(1000); //延迟1秒 }stopped = false;
}void MyThread::showValue()
{qDebug() << value << "show子线程id:"<< QThread::currentThreadId();emit sendValue(value); //数据发送给主线程value++;
}
5、其他不用更改
四、运行测试
1、Ctrl+R 运行
2、点击“开始”,2/3秒后点击停止,输出框显示如下:
3、注:
①子线程构造函数、被主线程调用的函数(stop())和信号槽方式调用的函数(doSendData())都是在主线程
②只有run()和run()调用的函数showValue()在子线程