1.mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
class MyThread : public QThread
{
Q_OBJECT
public:
explicit MyThread(QObject *parent = 0);
protected:
//QThread的虚函数
//线程处理函数
//不能直接调用,通过start()间接调用
void run();
signals:
void isDone();
public slots:
};
#endif // MYTHREAD_H
mythread.cpp
#include "mythread.h"
MyThread::MyThread(QObject *parent) : QThread(parent)
{
}
void MyThread::run()
{
//很复杂的数据处理
//需要耗时5s
sleep(5);
emit isDone();
}
mywidget.h
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget>
#include <QTimer> //定时器头文件
#include "mythread.h" //线程头文件
namespace Ui {
class MyWidget;
}
class MyWidget : public QWidget
{
Q_OBJECT
public:
explicit MyWidget(QWidget *parent = 0);
~MyWidget();
void dealTimeout(); //定时器槽函数
void dealDone(); //线程结束槽函数
void stopThread(); //停止线程槽函数
private slots:
void on_pushButton_clicked();
private:
Ui::MyWidget *ui;
QTimer *myTimer; //声明变量
MyThread *thread; //线程对象
};
#endif // MYWIDGET_H
mywidget.cpp
#include "mywidget.h"
#include "ui_mywidget.h"
#include <QThread>
#include <QDebug>
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);
connect(thread, &MyThread::isDone, this, &MyWidget::dealDone);
//当按窗口右上角x时,窗口触发destroyed()
connect(this, &MyWidget::destroyed, this, &MyWidget::stopThread);
}
void MyWidget::stopThread()
{
//停止线程
thread->quit();
//等待线程处理完手头动作
thread->wait();
}
void MyWidget::dealDone()
{
qDebug() << "it is over";
myTimer->stop(); //关闭定时器
}
void MyWidget::dealTimeout()
{
static int i = 0;
i++;
//设置lcd的值
ui->lcdNumber->display(i);
}
MyWidget::~MyWidget()
{
delete ui;
}
void MyWidget::on_pushButton_clicked()
{
//如果定时器没有工作
if(myTimer->isActive() == false)
{
myTimer->start(100);
}
//启动线程,处理数据
thread->start();
}
运行
2.
mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QObject>
class MyThread : public QObject
{
Q_OBJECT
public:
explicit MyThread(QObject *parent = 0);
//线程处理函数
void myTimeout();
void setFlag(bool flag = true);
signals:
void mySignal();
public slots:
private:
bool isStop;
};
#endif // MYTHREAD_H
mythread.cpp
#include "mythread.h"
#include <QThread>
#include <QDebug>
#include <QMessageBox>
MyThread::MyThread(QObject *parent) : QObject(parent)
{
isStop = false;
}
void MyThread::myTimeout()
{
while( !isStop )
{
QThread::sleep(1);
emit mySignal();
//QMessageBox::aboutQt(NULL);
qDebug() << "子线程号:" << QThread::currentThread();
if(isStop)
{
break;
}
}
}
void MyThread::setFlag(bool flag)
{
isStop = flag;
}
mywidget.h
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget>
#include "mythread.h"
#include <QThread>
namespace Ui {
class MyWidget;
}
class MyWidget : public QWidget
{
Q_OBJECT
public:
explicit MyWidget(QWidget *parent = 0);
~MyWidget();
void dealSignal();
void dealClose();
signals:
void startThread(); //启动子线程的信号
private slots:
void on_buttonStart_clicked();
void on_buttonStop_clicked();
private:
Ui::MyWidget *ui;
MyThread *myT;
QThread *thread;
};
#endif // MYWIDGET_H
mywiget.cpp
#include "mywidget.h"
#include "ui_mywidget.h"
#include <QDebug>
MyWidget::MyWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::MyWidget)
{
ui->setupUi(this);
//动态分配空间,不能指定父对象
myT = new MyThread;
//创建子线程
thread = new QThread(this);
//把自定义线程加入到子线程中
myT->moveToThread(thread);
connect(myT, &MyThread::mySignal, this, &MyWidget::dealSignal);
qDebug() << "主线程号:" << QThread::currentThread();
connect(this, &MyWidget::startThread, myT, &MyThread::myTimeout);
connect(this, &MyWidget::destroyed, this, &MyWidget::dealClose);
//线程处理函数内部,不允许操作图形界面
//connect()第五个参数的作用,连接方式:默认,队列,直接
//多线程时才有意义
//默认的时候
//如果是多线程,默认使用队列
//如果是单线程, 默认使用直接方式
//队列: 槽函数所在的线程和接收者一样
//直接:槽函数所在线程和发送者一样
}
MyWidget::~MyWidget()
{
delete ui;
}
void MyWidget::dealClose()
{
on_buttonStop_clicked();
delete myT;
}
void MyWidget::dealSignal()
{
static int i = 0;
i++;
ui->lcdNumber->display(i);
}
void MyWidget::on_buttonStart_clicked()
{
if(thread->isRunning() == true)
{
return;
}
//启动线程,但是没有启动线程处理函数
thread->start();
myT->setFlag(false);
//不能直接调用线程处理函数,
//直接调用,导致,线程处理函数和主线程是在同一个线程
//myT->myTimeout();
//只能通过 signal - slot 方式调用
emit startThread();
}
void MyWidget::on_buttonStop_clicked()
{
if(thread->isRunning() == false)
{
return;
}
myT->setFlag(true);
thread->quit();
thread->wait();
}
运行
3.利用多线程绘图
mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QObject>
#include <QImage>
class MyThread : public QObject
{
Q_OBJECT
public:
explicit MyThread(QObject *parent = 0);
//线程处理函数
void drawImage();
signals:
void updateImage(QImage temp);
public slots:
};
#endif // MYTHREAD_H
mythread.cpp
#include "mythread.h"
#include <QPainter>
#include <QPen>
#include <QBrush>
#include <QImage>
MyThread::MyThread(QObject *parent) : QObject(parent)
{
}
void MyThread::drawImage()
{
//定义QImage绘图设备
QImage image(500, 500, QImage::Format_ARGB32);
//定义画家,指定绘图设备
QPainter p(&image);
//定义画笔对象
QPen pen;
pen.setWidth(5); //设置宽度
//把画笔交给画家
p.setPen(pen);
//定义画刷
QBrush brush;
brush.setStyle(Qt::SolidPattern); //设置样式
brush.setColor(Qt::red); //设置颜色
//把画刷交给画家
p.setBrush(brush);
//定义5个点
QPoint a[] =
{
QPoint(qrand()%500, qrand()%500),
QPoint(qrand()%500, qrand()%500),
QPoint(qrand()%500, qrand()%500),
QPoint(qrand()%500, qrand()%500),
QPoint(qrand()%500, qrand()%500)
};
p.drawPolygon(a, 5);
//通过信号发送图片
emit updateImage(image);
}
mywidget.ui
mywidget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "mythread.h"
#include <QThread>
#include <QImage>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
//重写绘图事件
void paintEvent(QPaintEvent *);
void getImage(QImage); //槽函数
void dealClose(); //窗口关闭槽函数
private:
Ui::Widget *ui;
QImage image;
MyThread *myT; //自定义线程对象
QThread *thread; //子线程
};
#endif // WIDGET_H
mywidget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QThread>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//自定义类对象,分配空间,不可以指定父对象
myT = new MyThread;
//创建子线程
thread = new QThread(this);
//把自定义模块添加到子线程
myT->moveToThread(thread);
//启动子线程,但是,并没有启动线程处理函数
thread->start();
//线程处理函数,必须通过signal - slot 调用
connect(ui->pushButton, &QPushButton::pressed, myT, &MyThread::drawImage);
connect(myT, &MyThread::updateImage, this, &Widget::getImage);
connect(this, &Widget::destroyed, this, &Widget::dealClose);
}
Widget::~Widget()
{
delete ui;
}
void Widget::dealClose()
{
//退出子线程
thread->quit();
//回收资源
thread->wait();
delete myT;
}
void Widget::getImage(QImage temp)
{
image = temp;
update(); //更新窗口,间接调用paintEvent()
}
void Widget::paintEvent(QPaintEvent *)
{
QPainter p(this); //创建画家,指定绘图设备为窗口
p.drawImage(50, 50, image);
}
运行