方法一:Qt4.7及以前版本
1.创建一个类从QThread类派生
1)在项目中新建一个基于QObiect的c++ class类文件(例如MyThread ),生成MyThread .h和MyThread .cpp两个文件
2)在头文件MyThread .h中修改两处,a)将包含的头文件#include< QObiect >替换成#include < QThread >,b)将继承的基类class MyThread : public QObiect 修改为class MyThread : public QThread
3)在MyThread .cpp中,将MyThread::MyThread(QObject *parent) : QObject (parent)修改为MyThread::MyThread(QObject *parent) : QThread(parent)
2.在子线程类workThread.cpp中重写run函数,将处理操作写入该函数中,例如:
void MyThread::run()
{
//复杂的数据处理,需要耗时5秒,用sleep(5)代替
sleep(5);
emit isDone();//数据处理结束信号
}
3.在主线程mywidget.cpp中创建子线程 对象,启动子线程,调用start()函数,
例如
#include "mywidget.h"
#include "ui_mywidget.h"
#include
#include
MyWidget::MyWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::MyWidget)
{
ui->setupUi(this);
//定时器分配空间
mytimer=new QTimer(this);
//只有定时器启动,自动触发timeout()
connect(mytimer,&QTimer::timeout,this,&MyWidget::dealTimeout);
//线程分配空间
thread=new MyThread(this);
//线程函数处理完毕,发送isDone信号,窗口执行dealDone函数关闭定时器
connect(thread,&MyThread::isDone,this,&MyWidget::dealDone);
//当按下窗口右上角“X”关闭线程函数
connect(this,&MyWidget::destroyed,this,&MyWidget::stopThread);
}
MyWidget::~MyWidget()
{
delete ui;
}
void MyWidget::dealTimeout()
{
static int i=0;
i++;
ui->lcdNumber->display(i);
}
//按下启动按钮
void MyWidget::on_pushButton_clicked()
{
//如果定时器没有工作
if(mytimer->isActive()==false)
{
//定时器时间间隔为100毫秒(每隔100ms启动一次定时器)
mytimer->start(100);
}
//启动线程,处理数据
thread->start();
}
void MyWidget::dealDone()
{
qDebug()<<"over";
mytimer->stop();//关闭定时器
}
void MyWidget::stopThread()
{
//停止线程
thread->quit();
//等待线程处理完手头工作
thread->wait();
}
方法二:Qt4.8及以后版本
1.在项目中新建一个基于QObiect的c++ class类文件(例如MyThread ),生成MyThread .h和MyThread .cpp
2.在主线程函数中mywidget.cpp创建一个QThread类对象
//自定义线程动态分配空间,不能指定父对象
myT =new MyThread;
3.在主线程函数中mywidget.cpp中创建一个线程模板类对象
//创建子线程,分配内存空间同时指定父对象
thread =new QThread(this);
4.将线程模板类对象myT 移动到子线程thread中
//把自定义的线程加入到子线程中
myT->moveToThread(thread);
5.在主线程函数mywidget.cpp中启动子线程
//启动线程,但是没有启动线程处理函数
thread->start();//间接调用run函数
6.通过信号槽方式,执行线程模板类中的线程处理函数myTimeOut
以下过程如下:
1)ui界面上按下start按钮,自动触发槽信号函数void on_buttonStart_clicked();启动线程:thread->start(),并发送线程启动信号emit startThread()
//start按钮按下函数
void MyWidget::on_buttonStart_clicked()
{
//如果thread线程函数已经处于运行状态,跳出该函数,不执行以下部分
if(thread->isRunning()==true)
{
return;
}
//启动线程,但是没有启动线程处理函数
thread->start();//间接调用run函数
myT->setFlag(false);
//不能直接调用线程处理函数
//直接调用,导致线程处理函数和主线程是在同一个线程
//只能通过信号和槽的方式调用
// myT->myTimeOut();
//窗口发送信号,启动线程处理函数
emit startThread();
}
2)窗口发送startThread启动线程信号后,自定义线程函数myT执行myTimeOut函数
//窗口发送startThread启动线程信号,自定义线程函数myT执行myTimeOut函数
connect(this,&MyWidget::startThread,myT,&MyThread::myTimeOut);
3)在myTimeOut函数中设置一个sleep()一秒后发送mySignal信号,相当于一个定时器
//自定义子线程函数
void MyThread::myTimeOut()
{
//当isStop==ture的时候退出循环
while(isStop==false)
{
//每隔1秒发送一个信号
QThread::sleep(1);
emit mySignal();
qDebug()<<"子线程号:"<
4)自定义线程函数myT发送mySignal信号,窗口接收后,执行dealSignal函数,
//自定义线程函数myT发送mySignal信号,窗口接收后,执行dealSignal函数
connect(myT,&MyThread::mySignal,this,&MyWidget::dealSignal);
qDebug()<<"主线程号:"<
5)dealSignal实现在LCD上实时显示i值
//窗口信号处理函数,在LCD上显示i值
void MyWidget::dealSignal()
{
static int i=0;
i++;
ui->lcdNumber->display(i);
}
6)直到等待按下ui界面上的stop或退出程序按钮
按下stop按钮后:退出子程序
//stop按钮按下函数
void MyWidget::on_buttonStop_clicked()
{
//如果thread线程函数已经处于停止运行状态,跳出该函数,不执行以下部分
if(thread->isRunning()==false)
{
return;
}
//将标志值设置为true,此时退出自定义线程函数myT
myT->setFlag(true);
//子线程函数退出
thread->quit();
thread->wait();
}
按下退出按钮后:触发dealClose函数,退出子程序,关闭窗口,释放内存
//关闭窗口时,窗口执行dealClose
connect(this,&MyWidget::destroyed,this,&MyWidget::dealClose);
void MyWidget::dealClose()
{
on_buttonStop_clicked();
delete myT;//关闭窗口时释放myT内存
}
项目文件和简单界面图如下:
1.自定义线程模板对象myT,构造的时候不能指定父对象
2.在整个程序中,函数MyWidget(执行ui界面绘制与更新)相当于主线程,而mythread,相当于自定义的子线程,不能处理UI窗口(ui相关的类),只能处理一些数据相关的操作,不能涉及窗口