自定义线程类,继承于 QObject
#pragma once
#include <QObject>
class QtThread : public QObject
{
Q_OBJECT
public:
QtThread(QObject *parent = nullptr);
~QtThread();
//线程处理函数
void myTimeOut();
void setFlag(bool flag = true);
signals:
void mySignal();
private:
bool isStop; //线程起停标志位
};
#include "QtThread.h"
#include <QThread>
#include <QDebug>
QtThread::QtThread(QObject *parent)
: QObject(parent)
{
isStop = false;
}
QtThread::~QtThread()
{
}
void QtThread::myTimeOut()
{
while (!isStop)
{
qDebug() << QString::fromLocal8Bit("子线程号:") << QThread::currentThread();
QThread::sleep(1); //每间隔一秒发送一个信号
emit mySignal();
}
}
void QtThread::setFlag(bool flag)
{
isStop = flag;
}
注意问题:
1. 自定义线程类动态分配空间,不能指定父对象,所以关闭窗口,停止线程的时候必须手动释放空间。
2. 线程函数处理函数内部,不允许操作图形界面 会导致崩溃。
3. 不能通过自定义线程类的指针直接调用线程处理函数 ,必须通过信号和槽的方式调用(直接调用,导致线程处理函数和主线程在同一个线程,可打印当前线程号来判断)。
4.connect() 第五个参数的作用 ,连接方式 :默认,队列,直接 (多线程时才有意义,默认的时候 如果是多线程 ,默认使用队列。如果是单线程,默认使用直接方式。队列:槽函数所在线程和接收者一样。直接:槽函数所在线程和发送者一样)。
#pragma once
#include <QtWidgets/QWidget>
#include "ui_QtMyThread.h"
#include "QtThread.h"
#include <QThread>
class QtMyThread : public QWidget
{
Q_OBJECT
public:
QtMyThread(QWidget *parent = Q_NULLPTR);
signals:
void startThread(); //启动子线程的信号
private slots:
void slotStart();
void slotStop();
void slotDealSignal();
void slotDealCose();
private:
Ui::QtMyThreadClass ui;
QtThread *pmyThread;
QThread *pthread;
};
#include "QtMyThread.h"
#include <QDebug>
QtMyThread::QtMyThread(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
//动态分配空间 ,不能指定父对象
pmyThread = new QtThread;
//创建子线程
pthread = new QThread(this);
//把自定义线程加入到子线程中去
pmyThread->moveToThread(pthread);
connect(ui.button_Start, &QPushButton::clicked, this, &QtMyThread::slotStart);
connect(ui.button_Stop, &QPushButton::clicked, this, &QtMyThread::slotStop);
connect(pmyThread, &QtThread::mySignal, this, &QtMyThread::slotDealSignal);
qDebug() << QString::fromLocal8Bit("主线程号:") << QThread::currentThread();
connect(this, &QtMyThread::startThread, pmyThread, &QtThread::myTimeOut);
connect(this, &QtMyThread::destroyed, this, &QtMyThread::slotDealCose);
//线程函数处理函数内部,不允许操作图形界面
//connect() 第五个参数的作用 ,连接方式 :默认,队列,直接
//多线程时才有意义
//默认的时候 如果是多线程 ,默认使用队列
//如果是单线程,默认使用直接方式
//队列:槽函数所在线程和接收者一样
//直接:槽函数所在线程和发送者一样
}
void QtMyThread::slotStart()
{
if (pthread->isRunning()) //判断线程是否正在运行
{
return;
}
//启动线程 ,但是并没有启动线程处理函数
pthread->start();
pmyThread->setFlag(false);
//不能直接调用线程处理函数
//直接调用,导致线程处理函数和主线程在同一个线程 可打印出当前线程号判断
//pmyThread->myTimeOut();
//只能通过信号和槽的方式调用
emit startThread();
}
void QtMyThread::slotStop()
{
if (!pthread->isRunning())
{
return;
}
pmyThread->setFlag(true);
pthread->quit(); //线程退出
pthread->wait(); //等待线程处理完
}
void QtMyThread::slotDealSignal()
{
static int i = 0;
i++;
ui.lcdNumber->display(i);
}
void QtMyThread::slotDealCose()
{
slotStop();
delete pmyThread; //关闭窗口 释放空间(没有指定父对象,所以手动释放)
}