From 6e09de85028e017162325753bd3ef89d56850a9e Mon Sep 17 00:00:00 2001 From: giersch Date: Tue, 6 Nov 2007 11:17:24 +0000 Subject: [PATCH] . --- DrawingWindow.cpp | 283 +++++++++++++++++++++++++++++++++++----------- DrawingWindow.h | 1 - test/hello.cpp | 37 ++++-- 3 files changed, 242 insertions(+), 79 deletions(-) diff --git a/DrawingWindow.cpp b/DrawingWindow.cpp index 1f5bb6b..69e1d27 100644 --- a/DrawingWindow.cpp +++ b/DrawingWindow.cpp @@ -1,134 +1,275 @@ #include "DrawingWindow.h" +#include +#include +#include +#include #include +#include +#include #include #include -#include +class DrawingThread: public QThread { +public: + DrawingThread(DrawingWindow &w, DrawingWindow::ThreadFunction f); + void start_once(Priority priority = InheritPriority); -/* - TODO : - class DrawingWindowPrivate { ... } - externalize class DrawingThread -*/ +protected: + void run(); -DrawingWindow::DrawingWindow(ThreadFunction fun, int width, int height) +private: + DrawingWindow &drawingWindow; + DrawingWindow::ThreadFunction threadFunction; + bool started_once; + + friend class DrawingWindow; + friend class DrawingWindowPrivate; +}; + +class DrawingWindowPrivate { +public: + static const int paintInterval = 33; + + DrawingWindow * const q; + + QBasicTimer timer; + QMutex mutex; + + QImage *image; + QPainter *painter; + + QColor fgColor; + QColor bgColor; + + bool dirtyFlag; + QRect dirtyRect; + + DrawingThread *thread; + + DrawingWindowPrivate(DrawingWindow *w, + DrawingWindow::ThreadFunction f); + ~DrawingWindowPrivate(); + + void initialize(); + + void lock(); + void unlock(); + + void setDirtyRect(); + void setDirtyRect(int x, int y); + void setDirtyRect(int x1, int y1, int x2, int y2); + void setDirtyRect(const QRect &rect); + +}; + +//--- DrawingWindow ---------------------------------------------------- + +DrawingWindow::DrawingWindow(ThreadFunction f, int w, int h) : QWidget() + , width(w) + , height(h) + , d(new DrawingWindowPrivate(this, f)) { - initialize(fun, width, height); + d->initialize(); } DrawingWindow::DrawingWindow(QWidget *parent, - ThreadFunction fun, int width, int height) + ThreadFunction f, int w, int h) : QWidget(parent) + , width(w) + , height(h) + , d(new DrawingWindowPrivate(this, f)) { - initialize(fun, width, height); + d->initialize(); } DrawingWindow::DrawingWindow(QWidget *parent, Qt::WindowFlags flags, - ThreadFunction fun, int width, int height) + ThreadFunction f, int w, int h) : QWidget(parent, flags) + , width(w) + , height(h) + , d(new DrawingWindowPrivate(this, f)) { - initialize(fun, width, height); + d->initialize(); } -void DrawingWindow::initialize(ThreadFunction fun, int width, int height) +DrawingWindow::~DrawingWindow() { - image = new QImage(width, height, QImage::Format_RGB32); - image->fill(QColor(Qt::white).rgb()); + delete d; +} - painter = new QPainter(image); +void DrawingWindow::setColor(float red, float green, float blue) +{ + d->fgColor.setRgbF(red, green, blue); + QPen pen(d->painter->pen()); + pen.setColor(d->fgColor); + d->painter->setPen(pen); +} - dirtyFlag = false; +void DrawingWindow::setBgColor(float red, float green, float blue) +{ + d->bgColor.setRgbF(red, green, blue); +} - setFocusPolicy(Qt::StrongFocus); - setFixedSize(image->size()); - setAttribute(Qt::WA_OpaquePaintEvent); - setFocus(); - timer.start(paintInterval, this); +void DrawingWindow::clearGraph() +{ + d->lock(); + d->painter->fillRect(d->image->rect(), d->bgColor); + d->setDirtyRect(); + d->unlock(); +} - thread = new DrawingThread(*this, fun); - thread_started = false; +void DrawingWindow::drawPoint(int x, int y) +{ + d->lock(); + d->painter->drawPoint(x, y); + d->setDirtyRect(x, y); + d->unlock(); } -DrawingWindow::~DrawingWindow() +void DrawingWindow::drawLine(int x1, int y1, int x2, int y2) { - delete thread; - delete painter; - delete image; + d->lock(); + d->painter->drawLine(x1, y1, x2, y2); + d->setDirtyRect(x1, y1, x2, y2); + d->unlock(); } -void DrawingWindow::setColor(const QColor &color) +void DrawingWindow::drawRect(int x1, int y1, int x2, int y2) { - QPen pen(painter->pen()); - pen.setColor(color); - painter->setPen(pen); + QRect r; + r.setCoords(x1, y1, x2, y2); + r = r.normalized(); + d->lock(); + d->painter->drawRect(r); + r.adjust(0, 0, 1, 1); + d->setDirtyRect(r); + d->unlock(); } -void DrawingWindow::setColor(float red, float green, float blue) +void DrawingWindow::sleep(unsigned long secs) { - QColor color; - color.setRgbF(red, green, blue); - this->setColor(color); + DrawingThread::sleep(secs); } -void DrawingWindow::drawPoint(int x, int y) +void DrawingWindow::msleep(unsigned long msecs) { - lock(); - painter->drawPoint(x, y); - setDirtyRect(x, y); - unlock(); + DrawingThread::msleep(msecs); } -void DrawingWindow::drawLine(int x1, int y1, int x2, int y2) +void DrawingWindow::usleep(unsigned long usecs) { - lock(); - painter->drawLine(x1, y1, x2, y2); - setDirtyRect(x1, y1, x2, y2); - unlock(); + DrawingThread::usleep(usecs); } void DrawingWindow::closeEvent(QCloseEvent *ev) { - thread->terminate(); + d->timer.stop(); + d->thread->terminate(); QWidget::closeEvent(ev); - thread->wait(); + d->thread->wait(); } void DrawingWindow::paintEvent(QPaintEvent *ev) { QPainter widgetPainter(this); QRect rect = ev->rect(); - mutex.lock(); - QImage imageCopy(*image); - mutex.unlock(); + d->mutex.lock(); + QImage imageCopy(*d->image); + d->mutex.unlock(); widgetPainter.drawImage(rect, imageCopy, rect); } void DrawingWindow::showEvent(QShowEvent *ev) { - if (!thread_started) { - thread->start(); - thread_started = true; - } + d->timer.start(d->paintInterval, this); + d->thread->start_once(QThread::IdlePriority); QWidget::showEvent(ev); } void DrawingWindow::timerEvent(QTimerEvent *ev) { - if (ev->timerId() == timer.timerId()) { - mutex.lock(); - if (dirtyFlag) { - update(dirtyRect); - dirtyFlag = false; + if (ev->timerId() == d->timer.timerId()) { + d->mutex.lock(); + if (d->dirtyFlag) { + update(d->dirtyRect); + d->dirtyFlag = false; } - mutex.unlock(); - timer.start(paintInterval, this); + d->mutex.unlock(); + d->timer.start(d->paintInterval, this); } else { QWidget::timerEvent(ev); } } -void DrawingWindow::setDirtyRect(const QRect &rect) +//--- DrawingWindowPrivate --------------------------------------------- + +DrawingWindowPrivate::DrawingWindowPrivate(DrawingWindow *w, + DrawingWindow::ThreadFunction f) + : q(w) + , image(new QImage(q->width, q->height, QImage::Format_RGB32)) + , painter(new QPainter(image)) + , thread(new DrawingThread(*q, f)) +{ +} + +void DrawingWindowPrivate::initialize() +{ + q->setFocusPolicy(Qt::StrongFocus); + q->setFixedSize(image->size()); + q->setAttribute(Qt::WA_OpaquePaintEvent); + q->setFocus(); + + q->setColor(0.0, 0.0, 0.0); + q->setBgColor(1.0, 1.0, 1.0); + q->clearGraph(); + + dirtyFlag = false; +} + +DrawingWindowPrivate::~DrawingWindowPrivate() +{ + delete thread; + delete painter; + delete image; +} + +inline +void DrawingWindowPrivate::lock() +{ + thread->setTerminationEnabled(false); + mutex.lock(); +} + +inline +void DrawingWindowPrivate::unlock() +{ + mutex.unlock(); + thread->setTerminationEnabled(true); +} + +inline +void DrawingWindowPrivate::setDirtyRect() +{ + dirtyFlag = true; + dirtyRect = image->rect(); +} + +inline +void DrawingWindowPrivate::setDirtyRect(int x, int y) +{ + setDirtyRect(QRect(x, y, 1, 1)); +} + +inline +void DrawingWindowPrivate::setDirtyRect(int x1, int y1, int x2, int y2) +{ + QRect r; + r.setCoords(x1, y1, x2, y2); + setDirtyRect(r.normalized()); +} + +void DrawingWindowPrivate::setDirtyRect(const QRect &rect) { if (dirtyFlag) { dirtyRect |= rect; @@ -138,14 +279,24 @@ void DrawingWindow::setDirtyRect(const QRect &rect) } } -DrawingWindow::DrawingThread::DrawingThread(DrawingWindow &w, - ThreadFunction f) +//--- DrawingThread ---------------------------------------------------- + +DrawingThread::DrawingThread(DrawingWindow &w, DrawingWindow::ThreadFunction f) : drawingWindow(w) , threadFunction(f) + , started_once(false) { } -void DrawingWindow::DrawingThread::run() +void DrawingThread::start_once(Priority priority) +{ + if (!started_once) { + started_once = true; + start(priority); + } +} + +void DrawingThread::run() { threadFunction(drawingWindow); } diff --git a/DrawingWindow.h b/DrawingWindow.h index 7685d7d..9ddd4b7 100644 --- a/DrawingWindow.h +++ b/DrawingWindow.h @@ -1,7 +1,6 @@ #ifndef DRAWING_WINDOW_H #define DRAWING_WINDOW_H -#include #include #include diff --git a/test/hello.cpp b/test/hello.cpp index d98d2a6..40432e3 100644 --- a/test/hello.cpp +++ b/test/hello.cpp @@ -28,21 +28,21 @@ void flip(DrawingWindow &w) { - std::cout << "[ " << w.width() << " x " << w.height() << " ]\n"; + std::cout << "[ " << w.width << " x " << w.height << " ]\n"; int c = 0; int y = 0; -// int h = w.height(); -// int w = w.width(); +// int h = w.height; +// int w = w.width; int count = 50;//1 << 31; while (1) { // std::cerr << "loooooooooooooooooooooop " // << y << " (" << c << ")\n"; w.setColor(c, c, c); for (int yy = y; yy < y + 10; yy++) - for (int x = 0; x < w.width(); x++) + for (int x = 0; x < w.width; x++) w.drawPoint(x, yy); - if ((y += 10) >= w.height()) { + if ((y += 10) >= w.height) { y = 0; c = !c; if (!--count) break; @@ -55,8 +55,8 @@ void flip(DrawingWindow &w) void mandel(DrawingWindow &w) { /* paramètres par défaut */ - int larg = w.width(); - int haut = w.height(); + int larg = w.width; + int haut = w.height; float Rmin = -2.05; float Rmax = 0.55; float Imin = -1.3; @@ -120,8 +120,8 @@ void mandel(DrawingWindow &w) void lines(DrawingWindow &w) { int n = 100000; - int xmax = w.width(); - int ymax = w.height(); + int xmax = w.width; + int ymax = w.height; while (n-- > 0) { double r = rand() / (float )RAND_MAX; double g = rand() / (float )RAND_MAX; @@ -135,15 +135,28 @@ void lines(DrawingWindow &w) } } +void rectangles(DrawingWindow &w) +{ + int d = 5; + int z = (w.width > w.height ? w.height : w.width) / 2; + z = d * (z / d); + while (z > 0) { + w.drawRect(z, z, w.width - 1 - z, w.height - 1 - z); + z -= d; + } +} + int main(int argc, char *argv[]) { const int w = 1000; const int h = 700; QApplication application(argc, argv); - DrawingWindow dd(lines, w, h); - dd.show(); -// return application.exec(); + DrawingWindow dl(lines, w, h); + dl.show(); + + DrawingWindow dr(rectangles, w, h); + dr.show(); const int nf = 1; const int nm = 1; -- 2.20.1