前言
目的是在主线程中,使用信号和槽来执行一个子线程中的处理函数。
- 当点击start按钮时,子线程每秒钟发射一个信号(mySignal) 并在控制台打印线程地址,主线程接收此信号执行数字累加。
- 当点击stop按钮时,停止子线程,并释放内存。
- 当点击关闭窗口按钮时,可能子线程还在运行,此时就要触发stop按钮的信号执行停止子线程。
步骤
- 创建自定义类Thread继承QObject,并在槽函数中写相应的处理代码。
- 在主线程中创建一个Thread的对象myT,和QThread(子线程)的对象thread。
- 将myT加入到子线程中。
- 启动子线程thread(此时并没有执行myT中的处理函数myTimerout())。
- 通过主线程的信号startThread()唤醒子线程的函数myTimerout()。
- 子线程中myTimerout()发射信号mySignal(),主线程接收执行dealSignal()。
代码:
自定义类Thread:
thread.h
#include<QObject>
#include<QDebug>
#include<QThread>
class Thread : public QObject
{
Q_OBJECT
public:
Thread() ;
void set_flag(bool x) ;
signals:
void mySignal() ;
public slots:
void myTimerout();
private:
bool flag;
};
thread.cpp
#include"thread.h"
#include "QThread"
Thread::Thread()
{
flag = false ;
}
void Thread::set_flag(bool x)
{
this->flag = x ;
}
void Thread::myTimerout()
{
while(!flag)
{
for(long long i = 0; i < 500000000; i++) ;
emit mySignal() ;
qDebug() << QThread::currentThread() ;
}
}
classwindow.h
#ifndef CLASSWINDOW_H
#define CLASSWINDOW_H
#include <QtGui/QMainWindow>
#include <QDebug>
#include <QThread>
#include "ui_classwindow.h"
#include "thread.h"
class ClassWindow : public QMainWindow
{
Q_OBJECT
public:
ClassWindow(QWidget *parent = 0, Qt::WFlags flags = 0);
~ClassWindow();
private:
Ui::ClassWindowClass ui;
Thread *myT;
QThread *thread ;
signals:
void startThread() ;
public slots:
void startButton_licked() ;
void stopButton_clicked() ;
//处理子线程发射的信号的函数
void dealSignal() ;
};
#endif // CLASSWINDOW_H
classwindow.cpp
#include "classwindow.h"
ClassWindow::ClassWindow(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
//创建自定义线程类,动态分配空间,不能指定父对象
myT = new Thread ;
//创建子线程
thread = new QThread(this) ;
//把自定义线程加入到子线程中
myT->moveToThread(thread) ;
qDebug() << QThread::currentThread() ;
//主线程发射信号,子线程接收开始执行函数myTimout()
QObject::connect(this, SIGNAL(startThread()), myT, SLOT(myTimerout())) ;
//子线程中的myTimout()每秒发射一个信号,主线程执行dealSignal
QObject::connect(myT, SIGNAL(mySignal()), this, SLOT(dealSignal()));
//关闭按钮触发stop按钮来停止子线程
QObject::connect(this, SIGNAL(destroyed()), this, SLOT(stopButton_clicked())) ;
//线程处理函数不能操作图形用户界面
}
ClassWindow::~ClassWindow()
{
}
void ClassWindow::startButton_licked()
{
if(thread->isRunning())
return ;
myT->set_flag(false) ;
thread->start() ;
emit startThread() ;
}
void ClassWindow::stopButton_clicked()
{
if(thread->isFinished())
return ;
myT->set_flag(true) ;
thread->quit() ;
thread->wait() ;
delete myT ;
}
void ClassWindow::dealSignal()
{
static int i = 0;
i++;
ui.lcdNumber->display(i) ;
}
运行时可以看到,控制台上显示的主线程和子线程不是一个地址。