现阶段可以实现koch分形雪花,但是是一次性全部显示出来的,而不是慢慢生长出来 帮帮忙
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分形雪花的实时绘制效果。
#include "mainwindow.h"
#include <QtCore>
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QThread>
class KochSnowflake : public QWidget
{
public:
KochSnowflake(QWidget *parent = nullptr) : QWidget(parent), level(0) {}
void setLevel(int newLevel)
{
level = newLevel;
update();
}
protected:
void paintEvent(QPaintEvent *event) override
{
Q_UNUSED(event);
QPainter painter(this);
drawSnowflake(painter, level, width() / 2, height() / 2, qMin(width(), height()) / 2 - 10);
}
private:
void drawSnowflake(QPainter &painter, int level, int x, int y, int size)
{
if (level == 0)
{
drawLine(painter, x, y, x + size, y);
drawLine(painter, x + size, y, x + size / 2, y - size * qSqrt(3) / 2);
drawLine(painter, x + size / 2, y - size * qSqrt(3) / 2, x, y);
}
else
{
int newSize = size / 3;
drawSnowflake(painter, level - 1, x, y, newSize);
drawSnowflake(painter, level - 1, x + newSize, y, newSize);
drawSnowflake(painter, level - 1, x + newSize / 2, y - newSize * qSqrt(3) / 2, newSize);
drawSnowflake(painter, level - 1, x + 2 * newSize, y, newSize);
drawSnowflake(painter, level - 1, x + 2 * newSize, y + newSize * qSqrt(3), newSize);
drawSnowflake(painter, level - 1, x + newSize, y + newSize * qSqrt(3), newSize);
drawSnowflake(painter, level - 1, x + newSize / 2, y + newSize * qSqrt(3) / 2, newSize);
drawSnowflake(painter, level - 1, x, y + newSize * qSqrt(3), newSize);
}
}
void drawLine(QPainter &painter, int x1, int y1, int x2, int y2)
{
painter.drawLine(x1, y1, x2, y2);
}
int level;
};
class SnowflakeThread : public QThread
{
public:
explicit SnowflakeThread(KochSnowflake *snowflake) : snowflake(snowflake) {}
void setLevel(int level)
{
QMutexLocker locker(&mutex);
this->level = level;
}
protected:
void run() override
{
while (!isInterruptionRequested())
{
QMutexLocker locker(&mutex);
snowflake->setLevel(level);
level = (level + 1) % 6;
msleep(1000);
}
}
private:
QMutex mutex;
KochSnowflake *snowflake;
int level = 0;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
KochSnowflake snowflake;
SnowflakeThread snowflakeThread(&snowflake);
snowflakeThread.start();
snowflake.show();
a.exec();
snowflakeThread.requestInterruption();
snowflakeThread.wait();
return 0;
}