Qt 多线程专栏

  • 主线程就是进程,进程代表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);//起点坐标,图片有多大画多大
}

在这里插入图片描述

  • 多线程实例:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_42308217/article/details/113386218