栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【Qt】Q多线程开发—多线程应用示例分析(Mandelbrot)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【Qt】Q多线程开发—多线程应用示例分析(Mandelbrot)

Qt-多线程应用示例分析(Mandelbrot)

文章目录

Qt-多线程应用示例分析(Mandelbrot)一、写在前面二、RendThread类的定义

(2-1)run()函数实现(2-2)render()函数的实现 三、MandelbrotWidget类的定义四、总结

一、写在前面

​ 本文章讨论内容是:关于Qt的多线程应用,创建线程的方法是:子类化QThread创建线程,重载run()函数实现多线程。

​ (注)本文所有代码出自官方示例《Mandelbrot Example》

​ 《Mandelbrot Example》示例包含两个类:

1、RenderThread是一个QThread子类,用于呈现Mandelbrot集合。
  2、MandelbrotWidget是一个QWidget子类,用于在屏幕上显示Mandelbrot集合,并绑定鼠标缩放和滚动事件处理功能。

二、RendThread类的定义
#include 
#include 
#include 
#include 

QT_BEGIN_NAMESPACE
class QImage;
QT_END_NAMESPACE

//! [0]
class RenderThread : public QThread
{
    Q_OBJECT

public:
    RenderThread(QObject *parent = nullptr);
    ~RenderThread();

    void render(double centerX, double centerY, double scaleFactor, QSize resultSize);

signals:
    void renderedImage(const QImage &image, double scaleFactor);

protected:
    void run() override;

private:
    uint rgbFromWaveLength(double wave);

    QMutex mutex;
    QWaitCondition condition;
    double centerX;
    double centerY;
    double scaleFactor;
    QSize resultSize;
    bool restart;
    bool abort;

    enum { ColormapSize = 512 };
    uint colormap[ColormapSize];
};

​ 1、该类继承了QThread,因此它能够在单独的线程中运行。除了构造函数和析构函数外,render()是唯一的公共函数。每当线程渲染一个图像时,都会发出renderedImage()信号。renderedImage()信号将与MandelbrotWidget类的updatePixmap槽函数相连接,用于更新QPixmap。以便于MandelbrotWidget类的paintEvent()绘图事件函数对经过RenderThread线程渲染后的Pixmap绘制。如下代码片段:

connect(&thread, &RenderThread::renderedImage,this, &MandelbrotWidget::updatePixmap);

2、在QThread子类中重新实现受保护的run()函数,在线程启动时自动调用它。

​ 3、在私有部分中,有一个QMutex、一个QWaitCondition和一些其他的数据成员。互斥锁保护另一个数据成员。

(2-1)run()函数实现
void RenderThread::run()
{
  forever {
        mutex.lock();
        QSize resultSize = this->resultSize;
        double scaleFactor = this->scaleFactor;
        double centerX = this->centerX;
        double centerY = this->centerY;
        mutex.unlock();
 
        int halfWidth = resultSize.width() / 2;
 
        int halfHeight = resultSize.height() / 2;
        QImage image(resultSize, QImage::Format_RGB32);

        const int NumPasses = 8;
        int pass = 0;
        while (pass < NumPasses) {
            const int MaxIterations = (1 << (2 * pass + 6)) + 32;
            const int Limit = 4;
            bool allBlack = true;

             for (int y = -halfHeight; y < halfHeight; ++y) {
                 if (restart)
                     break;
                 if (abort)
                     return;
 
                 uint *scanLine =
                         reinterpret_cast(image.scanLine(y + halfHeight));
                 double ay = centerY + (y * scaleFactor);
 
                for (int x = -halfWidth; x < halfWidth; ++x) {
                     double ax = centerX + (x * scaleFactor);
                     double a1 = ax;
                     double b1 = ay;
                     int numIterations = 0;
 
                     do {
                         ++numIterations;
                         double a2 = (a1 * a1) - (b1 * b1) + ax;
                         double b2 = (2 * a1 * b1) + ay;
                         if ((a2 * a2) + (b2 * b2) > Limit)
                             break;
 
                         ++numIterations;
                         a1 = (a2 * a2) - (b2 * b2) + ax;
                         b1 = (2 * a2 * b2) + ay;
                         if ((a1 * a1) + (b1 * b1) > Limit)
                             break;
                     } while (numIterations < MaxIterations);
 
                     if (numIterations < MaxIterations) {
                         *scanLine++ = colormap[numIterations % ColormapSize];
                         allBlack = false;
                     } else {
                         *scanLine++ = qRgb(0, 0, 0);
                     }
                 }
             }//for END
       
             if (allBlack && pass == 0) {
                 pass = 4;
             } else {
                 if (!restart)
                     emit renderedImage(image, scaleFactor);  
                 ++pass;
             }
         }//While END
 
         mutex.lock();
 
         if (!restart)
             condition.wait(&mutex);
         restart = false;
         mutex.unlock();
     }
}
(2-2)render()函数的实现
void RenderThread::render(double centerX, double centerY, double scaleFactor,
                          QSize resultSize)
{
    QMutexLocker locker(&mutex);

    this->centerX = centerX;
    this->centerY = centerY;
    this->scaleFactor = scaleFactor;
    this->resultSize = resultSize;

    if (!isRunning()) {
        start(LowPriority);
    } else {
        restart = true;
        condition.wakeOne();
    }
}
三、MandelbrotWidget类的定义
class MandelbrotWidget : public QWidget
{
    Q_OBJECT

public:
    MandelbrotWidget(QWidget *parent = nullptr);

protected:
    void paintEvent(QPaintEvent *event) override;
    void resizeEvent(QResizeEvent *event) override;
    void keyPressEvent(QKeyEvent *event) override;
#if QT_ConFIG(wheelevent)
    void wheelEvent(QWheelEvent *event) override;
#endif
    void mousePressEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;

private slots:
    void updatePixmap(const QImage &image, double scaleFactor);
    void zoom(double zoomFactor);

private:
    void scroll(int deltaX, int deltaY);

    RenderThread thread;
    QPixmap pixmap;
    QPoint pixmapOffset;
    QPoint lastDragPos;
    double centerX;
    double centerY;
    double pixmapScale;
    double curScale;
};
四、总结

​ 1、RendThread类与MandelbrotWidget类通过信号和槽机制进行关联:用于更新MandelbrotWidget类中所使用的Pixmap数据,然后在paintEvent()绘图事件函数中进行绘制。

​ 2、MandelbrotWidget类通过调用RendThread类的render(double centerX, double centerY, double scaleFactor, QSize resultSize)成员函数向RendThread类中传递数据并启动RendThread类线程进行计算。

​ 3、Qt中Widgets部件(例如QPushButton、QLabel等)不能在其他线程中创建,只能在GUI线程中创建。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/737868.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号