only if else 2023-06-21 14:41 采纳率: 0%
浏览 82

怎么用qt、多线程实现koch分形雪花实时绘制

现阶段可以实现koch分形雪花,但是是一次性全部显示出来的,而不是慢慢生长出来 帮帮忙

  • 写回答

3条回答 默认 最新

  • 易只轻松熊 2023-06-21 14:51
    关注
    
    main.cpp
    
    Copy
    #include "mainwindow.h"
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
        return a.exec();
    }
    mainwindow.h
    
    Copy
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QThread>
    #include <QMutex>
    #include <QWaitCondition>
    
    class FractalThread;
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    protected:
        void paintEvent(QPaintEvent *);
    
    private:
        Ui::MainWindow *ui;
        FractalThread *thread;
        QMutex mutex;
        QWaitCondition condition;
        bool stop;
    
    private slots:
        void on_startButton_clicked();
        void on_stopButton_clicked();
    };
    
    #endif // MAINWINDOW_H
    mainwindow.cpp
    
    Copy
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "fractalthread.h"
    #include <QPainter>
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow),
        thread(nullptr),
        stop(false)
    {
        ui->setupUi(this);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::paintEvent(QPaintEvent *)
    {
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
    
        mutex.lock();
        if (thread != nullptr)
        {
            painter.drawImage(0, 0, thread->image());
        }
        mutex.unlock();
    }
    
    void MainWindow::on_startButton_clicked()
    {
        if (thread == nullptr)
        {
            thread = new FractalThread(this);
            thread->start();
        }
        else
        {
            mutex.lock();
            stop = false;
            condition.wakeAll();
            mutex.unlock();
        }
    }
    
    void MainWindow::on_stopButton_clicked()
    {
        mutex.lock();
        stop = true;
        condition.wakeAll();
        mutex.unlock();
    }
    
    FractalThread
    
    ```c++
    #ifndef FRACTALTHREAD_H
    #define FRACTALTHREAD_H
    
    #include <QObject>
    #include <QThread>
    #include <QImage>
    #include <QMutex>
    #include <QWaitCondition>
    
    class FractalThread : public QThread
    {
        Q_OBJECT
    
    public:
        FractalThread(QObject *parent = nullptr);
        ~FractalThread();
    
        QImage image() const;
    
    protected:
        void run();
    
    private:
        QImage img;
        QMutex mutex;
        QWaitCondition condition;
        bool stop;
    
        void drawKoch(QPainter &painter, QPointF p1, QPointF p2, int level);
    
    signals:
        void updated();
    };
    
    #endif // FRACTALTHREAD_H
    fractalthread.cpp
    
    Copy
    #include "fractalthread.h"
    #include <QPainter>
    #include <cmath>
    
    FractalThread::FractalThread(QObject *parent) :
        QThread(parent),
        img(800, 800, QImage::Format_RGB32),
        stop(false)
    {
        img.fill(Qt::white);
    }
    
    FractalThread::~FractalThread()
    {
        wait();
    }
    
    QImage FractalThread::image() const
    {
        return img;
    }
    
    void FractalThread::run()
    {
        QPainter painter(&img);
        painter.setRenderHint(QPainter::Antialiasing);
    
        QPointF p1(400, 50);
        QPointF p2(100, 650);
        QPointF p3(700, 650);
        drawKoch(painter, p1, p2, 5);
        drawKoch(painter, p2, p3, 5);
        drawKoch(painter, p3, p1, 5);
    
        mutex.lock();
        while (!stop)
        {
            condition.wait(&mutex);
        }
        mutex.unlock();
    }
    
    void FractalThread::drawKoch(QPainter &painter, QPointF p1, QPointF p2, int level)
    {
        if (level == 0)
        {
            painter.drawLine(p1, p2);
        }
        else
        {
            QPointF p3 = p1 + (p2 - p1) / 3;
            QPointF p4 = p1 + (p2 - p1) * 2 / 3;
            QPointF p5 = p3 + QPointF(cos(M_PI / 3) * (p4 - p3).y() - sin(M_PI / 3) * (p4 - p3).x(),
                                       sin(M_PI / 3) * (p4 - p3).y() + cos(M_PI / 3) * (p4 - p3).x());
    
            drawKoch(painter, p1, p3, level - 1);
            drawKoch(painter, p3, p5, level - 1);
            drawKoch(painter, p5, p4, level - 1);
            drawKoch(painter, p4, p2, level - 1);
        }
    
        emit updated();
    }
    

    在运行程序时,点击“开始”按钮将启动线程并绘制Koch分形雪花,点击“停止”按钮将暂停线程。由于绘制线程和主线程是两个独立的线程,因此需要使用互斥量和条件变量来同步它们之间的操作。在绘制线程中,每绘制一次分形雪花就会发出更新信号,主线程接收到更新信号后会重新绘制窗口。这样就实现了Koch分形雪花的实时绘制效果。

    评论

报告相同问题?

问题事件

  • 创建了问题 6月21日