Qt 线程的创建和使用(二)

自定义线程类,继承于 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;	//关闭窗口 释放空间(没有指定父对象,所以手动释放)
}

你可能感兴趣的:(Qt基础)