0. 写在前面
Qt-线程1-Run-CSDN博客
上一篇介绍了为何要使用线程,这篇介绍第二种线程编写方式;这种方式代码写起来复杂一些,硬币总是有两个面,虽然写起来复杂,但是逻辑是很清晰的。
(1)新建自己的Thread的类,用于完成自己想执行的函数,设置一个标志位,用于随时启动或者停止线程;
(2)新创建一个QThread的类,利用moveToThread方法,将自己的类放进QThread线程中;
(3)利用signal-slot,信号与槽的方式将子线程和主线程连接起来,最后注意摧毁,关闭掉线程即可。
1. 全部代码
### mythread.h ###
#ifndef MYTHREAD_H
#define MYTHREAD_H#include <QObject>class mythread : public QObject
{Q_OBJECT
public:explicit mythread(QObject *parent = nullptr);//线程处理函数void myTimeout();void setFlag(bool flag = true);signals:void mySignal();public slots:private:bool isStop;
};#endif // MYTHREAD_H### qtthreadmov.h ###
#ifndef QTHREADMOVE_H
#define QTHREADMOVE_H#include <QWidget>
#include "mythread.h"
#include <QThread>namespace Ui {
class QThreadMove;
}class QThreadMove : public QWidget
{Q_OBJECTpublic:explicit QThreadMove(QWidget *parent = 0);~QThreadMove();void dealSignal();signals:void startThread(); //启动子线程的信号private slots:void on_pBtn_start_clicked();void on_pBtn_stop_clicked();void dealClose();private:Ui::QThreadMove *ui;mythread* myT;QThread* thread1;};#endif // QTHREADMOVE_H### mythread.cpp ###
#include "mythread.h"
#include <QThread>
#include <QDebug>mythread::mythread(QObject *parent) : QObject(parent)
{isStop = false;}void mythread::myTimeout()
{while(!isStop){QThread::sleep(1);emit mySignal();qDebug() << "子线程号:" << QThread::currentThread();if(isStop){break;}}}void mythread::setFlag(bool flag)
{isStop = flag;
}### qtthreadmove.cpp ###
#include "qthreadmove.h"
#include "ui_qthreadmove.h"
#include <QDebug>QThreadMove::QThreadMove(QWidget *parent) :QWidget(parent),ui(new Ui::QThreadMove)
{ui->setupUi(this);//动态分配空间,不能指定父对象,自己创建的线程类myT = new mythread;//创建子线程thread1 = new QThread(this);//自定义线程加入到子线程中myT->moveToThread(thread1);//子线程处理完数据之后返回信号,主线程做处理connect(myT,&mythread::mySignal,this,&QThreadMove::dealSignal);qDebug() << "主线程号:" << QThread::currentThread();//打开线程开关//主线程给子线程开关指令,子线程执行函数操作connect(this,&QThreadMove::startThread,myT,&mythread::myTimeout);//销毁线程connect(this,&QThreadMove::destroyed,this,&QThreadMove::dealClose);//线程处理函数内部,不允许操作图形界面//conncet()第五个参数的作用,连接方式:默认,队列,直接//如果是多线程,默认是队列,如果是单线程,默认是直接方式//队列:槽函数所在线程和信号接收者一样}QThreadMove::~QThreadMove()
{delete ui;
}void QThreadMove::on_pBtn_start_clicked()
{if(thread1->isRunning() == true){return;}//如果启动线程,但是没有启动线程处理函数thread1->start();myT->setFlag(false);//不能直接调用线程处理函数,直接调用,导致线程处理函数和主线程是在同一个线程//myT->myTimeout();//只能通过signal-slot的方式来调用emit startThread();}void QThreadMove::dealSignal()
{static int i = 0;i++;ui->lcdNumber->display(i);
}void QThreadMove::on_pBtn_stop_clicked()
{if(thread1->isRunning() == false){return;}myT->setFlag(true);thread1->quit();thread1->wait();
}void QThreadMove::dealClose()
{on_pBtn_stop_clicked();
}