【QT】Qt线程三个实例 包含利用线程绘图

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);
}

运行

发布了201 篇原创文章 · 获赞 46 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/rong11417/article/details/104743995