-
主线程就是进程,进程代表4个G的资源空间,主线程退出就意味着进程退出,在Qt中,主线程不能是子线程的父对象,因此必须在线程的析构函数中去delete线程对象。
-
只要定时器启动,自动触发timeout()信号
-
类A继承了Tread类,在A中写run方法,就会覆盖掉Thread中的run方法,所以此时调用start方法后,实现的是自己的run方法体里面的代码。start()相当于间接的调用run(),如果我们直接调用子线程的run()方法,其方法还是运行在主线程中,代码在程序中是顺序执行的,所以不会有解决耗时操作的问题。所以不能直接调用线程的run()方法,只有子线程开始了,才会有异步的效果。当thread.start()方法执行了以后,子线程才会执行run()方法,这样的效果和在主线程中直接调用run()方法的效果是截然不同的。
-
于是这里就不需要改变了:
mythread.h:
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QObject>
class MyThread : public QObject
{
Q_OBJECT
public:
explicit MyThread(QObject *parent = nullptr);
//线程处理函数
void myTimeout();
void setFlag(bool flag = true);
signals:
void mySignal();
private:
bool isStop;
};
#endif // MYTHREAD_H
widget.h:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <mythread.h>
#include <QThread>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
void dealSignal();
void dealClose();
private slots:
void on_pushButton_2_clicked();
void on_pushButton_clicked();
signals:
void startThread();//启动子线程的信号
private:
Ui::Widget *ui;
MyThread *myT;
QThread *thread;
};
#endif // WIDGET_H
mythread.cpp:
#include "mythread.h"
#include <QThread>//睡觉用
MyThread::MyThread(QObject *parent) : QObject(parent)
{
isStop = false;
}
void MyThread::myTimeout()
{
while (isStop == false)
{
QThread::sleep(1);
emit mySignal();
if(true == isStop)
{ break;
}
}
}
void MyThread::setFlag(bool flag)
{
isStop = flag;
}
widget.cpp:
#include "widget.h"
#include "ui_widget.h"
#include <QThread>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//这里并不是两个线程,myT定义线程函数,thread才是子线程
//动态分配空间,不能指定父对象,因为子线程是myT的父亲,如果指定父对象,那么就有两个父对象,是不对的,会报错。
myT = new MyThread();
//创建子线程
thread = new QThread(this);
//把自定义线程函数加入到子线程中
myT->moveToThread(thread);
connect(myT,&MyThread::mySignal,this,&Widget::dealSignal);
connect(this,&Widget::startThread,myT,&MyThread::myTimeout);
connect(this,&Widget::destroyed,this,&Widget::dealClose);
}
void Widget::dealSignal()
{
static int i = 0;
i++;
ui->lcdNumber->display(i);
}
Widget::~Widget()
{
delete ui;
}
void Widget::dealClose()
{
on_pushButton_clicked();
}
void Widget::on_pushButton_2_clicked()
{
if(thread->isRunning() == true)
{
return;
}
//启动线程,但是没有启动线程处理函数
thread->start();
myT->setFlag(false);
//不能直接调用线程处理函数,否则导致线程处理函数和主线程在同一个线程,结果是无响应,只能通过信号和槽调用
emit startThread();
}
void Widget::on_pushButton_clicked()
{
if(thread->isRunning() == false)
{
return;
}
myT->setFlag(true);
thread->quit();
thread->wait();
}
myThread.h:
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QObject>
#include <QImage>
class MyThread : public QObject
{
Q_OBJECT
public:
explicit MyThread(QObject *parent = nullptr);
//线程处理函数
void drawImage();
signals:
void updateImage(QImage);//函数声明形参名称可加可不加
};
#endif // MYTHREAD_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QImage>
#include "mythread.h"
#include <QThread>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
//重写绘图事件
void paintEvent(QPaintEvent *);
void getImage(QImage);//槽函数
void dealClose();//窗口关闭槽函数
private:
Ui::Widget *ui;
QImage image;
MyThread *myT;//自定义线程对象
QThread *thread;//子线程
};
#endif // WIDGET_H
mythread.cpp:
#include "mythread.h"
#include <QPainter>
#include <QImage>
#include <QPen>
#include <QBrush>
MyThread::MyThread(QObject *parent) : QObject(parent)
{
}
void MyThread::drawImage()
{
//定义绘图设备
QImage image(500,500,QImage::Format_ARGB32);//_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);
//定义五个点
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);
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
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();
//线程处理函数必须通过信号槽调用
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();//回收资源
}
void Widget::getImage(QImage temp)
{
image = temp;
update();//更新窗口 间接调用paintEvent
}
void Widget::paintEvent(QPaintEvent *)
{
QPainter p(this);//创建画家,指定绘图设备为窗口
p.drawImage(50,50,image);//起点坐标,图片有多大画多大
}