-
主线程就是进程,进程代表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_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic: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_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic: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);//起点坐标,图片有多大画多大
}
























