1 #include "DrawingWindow.h"
2 #include <QApplication>
7 class DrawingThread: public QThread {
9 DrawingThread(DrawingWindow &w, DrawingWindow::ThreadFunction f);
10 void start_once(Priority priority = InheritPriority);
16 DrawingWindow &drawingWindow;
17 DrawingWindow::ThreadFunction threadFunction;
20 friend class DrawingWindow;
23 //--- DrawingWindow ----------------------------------------------------
25 DrawingWindow::DrawingWindow(ThreadFunction f, int w, int h)
33 DrawingWindow::DrawingWindow(QWidget *parent,
34 ThreadFunction f, int w, int h)
42 DrawingWindow::DrawingWindow(QWidget *parent, Qt::WindowFlags flags,
43 ThreadFunction f, int w, int h)
44 : QWidget(parent, flags)
51 DrawingWindow::~DrawingWindow()
58 void DrawingWindow::setColor(unsigned int color)
60 setColor(QColor::fromRgb(color));
63 void DrawingWindow::setColor(const char *name)
65 setColor(QColor(name));
68 void DrawingWindow::setColor(float red, float green, float blue)
70 setColor(QColor::fromRgbF(red, green, blue));
73 void DrawingWindow::setBgColor(unsigned int color)
75 setBgColor(QColor::fromRgb(color));
78 void DrawingWindow::setBgColor(const char *name)
80 setBgColor(QColor(name));
83 void DrawingWindow::setBgColor(float red, float green, float blue)
85 setBgColor(QColor::fromRgbF(red, green, blue));
88 void DrawingWindow::clearGraph()
91 painter->fillRect(image->rect(), getBgColor());
93 safeUnlock(imageMutex);
96 void DrawingWindow::drawPoint(int x, int y)
99 painter->drawPoint(x, y);
101 safeUnlock(imageMutex);
104 void DrawingWindow::drawLine(int x1, int y1, int x2, int y2)
106 safeLock(imageMutex);
107 painter->drawLine(x1, y1, x2, y2);
108 dirty(x1, y1, x2, y2);
109 safeUnlock(imageMutex);
112 void DrawingWindow::drawRect(int x1, int y1, int x2, int y2)
115 r.setCoords(x1, y1, x2 - 1, y2 - 1);
117 safeLock(imageMutex);
118 painter->drawRect(r);
119 r.adjust(0, 0, 1, 1);
121 safeUnlock(imageMutex);
124 void DrawingWindow::fillRect(int x1, int y1, int x2, int y2)
126 painter->setBrush(getColor());
127 drawRect(x1, y1, x2, y2);
128 painter->setBrush(Qt::NoBrush);
131 void DrawingWindow::drawCircle(int x, int y, int r)
134 rect.setCoords(x - r, y - r, x + r - 1, y + r - 1);
135 safeLock(imageMutex);
136 painter->drawEllipse(rect);
137 rect.adjust(0, 0, 1, 1);
139 safeUnlock(imageMutex);
142 void DrawingWindow::fillCircle(int x, int y, int r)
144 painter->setBrush(getColor());
146 painter->setBrush(Qt::NoBrush);
149 void DrawingWindow::drawText(int x, int y, const char *text, int flags)
151 QRect r(image->rect());
152 switch (flags & Qt::AlignHorizontal_Mask) {
156 case Qt::AlignHCenter:
158 r.setLeft(2 * x - width + 1);
165 switch (flags & Qt::AlignVertical_Mask) {
166 case Qt::AlignBottom:
169 case Qt::AlignVCenter:
171 r.setTop(2 * y - height + 1);
178 safeLock(imageMutex);
179 painter->drawText(r, flags, text, &r);
181 safeUnlock(imageMutex);
184 void DrawingWindow::drawTextBg(int x, int y, const char *text, int flags)
186 painter->setBackgroundMode(Qt::OpaqueMode);
187 drawText(x, y, text, flags);
188 painter->setBackgroundMode(Qt::TransparentMode);
191 unsigned int DrawingWindow::getPointColor(int x, int y)
193 return image->pixel(x, y);
196 bool DrawingWindow::sync(unsigned long time)
200 if (terminateThread) {
203 qApp->postEvent(this, new QEvent(QEvent::User));
204 synced = syncCondition.wait(&syncMutex, time);
206 safeUnlock(syncMutex);
210 void DrawingWindow::closeGraph()
212 qApp->postEvent(this, new QEvent(QEvent::Type(QEvent::User + 1)));
215 void DrawingWindow::sleep(unsigned long secs)
217 DrawingThread::sleep(secs);
220 void DrawingWindow::msleep(unsigned long msecs)
222 DrawingThread::msleep(msecs);
225 void DrawingWindow::usleep(unsigned long usecs)
227 DrawingThread::usleep(usecs);
230 void DrawingWindow::closeEvent(QCloseEvent *ev)
235 terminateThread = true; // this flag is needed for the case
236 // where the following wakeAll() call
237 // occurs between the
238 // setTerminationEnable(false) and the
239 // mutex lock in safeLock() called
241 syncCondition.wakeAll();
243 QWidget::closeEvent(ev);
247 void DrawingWindow::customEvent(QEvent *ev)
249 switch ((int )ev->type()) {
252 qApp->sendPostedEvents(this, QEvent::UpdateLater);
253 qApp->sendPostedEvents(this, QEvent::UpdateRequest);
254 qApp->sendPostedEvents(this, QEvent::Paint);
255 qApp->processEvents(QEventLoop::ExcludeUserInputEvents |
256 QEventLoop::ExcludeSocketNotifiers |
257 QEventLoop::DeferredDeletion |
258 QEventLoop::X11ExcludeTimers);
262 syncCondition.wakeAll();
265 case QEvent::User + 1:
271 void DrawingWindow::keyPressEvent(QKeyEvent *ev)
286 void DrawingWindow::paintEvent(QPaintEvent *ev)
288 QPainter widgetPainter(this);
290 QImage imageCopy(*image);
292 QRect rect = ev->rect();
293 widgetPainter.drawImage(rect, imageCopy, rect);
296 void DrawingWindow::showEvent(QShowEvent *ev)
298 timer.start(paintInterval, this);
299 thread->start_once(QThread::IdlePriority);
300 QWidget::showEvent(ev);
303 void DrawingWindow::timerEvent(QTimerEvent *ev)
305 if (ev->timerId() == timer.timerId()) {
307 timer.start(paintInterval, this);
309 QWidget::timerEvent(ev);
313 //--- DrawingWindow (private methods) ----------------------------------
315 void DrawingWindow::initialize(DrawingWindow::ThreadFunction f)
317 terminateThread = false;
319 image = new QImage(width, height, QImage::Format_RGB32);
320 painter = new QPainter(image);
321 thread = new DrawingThread(*this, f);
323 setFocusPolicy(Qt::StrongFocus);
324 setFixedSize(image->size());
325 setAttribute(Qt::WA_OpaquePaintEvent);
336 void DrawingWindow::setColor(const QColor& color)
338 QPen pen(painter->pen());
340 painter->setPen(pen);
344 void DrawingWindow::setBgColor(const QColor& color)
346 painter->setBackground(color);
350 QColor DrawingWindow::getColor()
352 return painter->pen().color();
356 QColor DrawingWindow::getBgColor()
358 return painter->background().color();
362 void DrawingWindow::safeLock(QMutex &mutex)
364 if (lockCount++ == 0)
365 thread->setTerminationEnabled(false);
370 void DrawingWindow::safeUnlock(QMutex &mutex)
373 if (--lockCount == 0)
374 thread->setTerminationEnabled(true);
378 void DrawingWindow::dirty()
381 dirtyRect = image->rect();
385 void DrawingWindow::dirty(int x, int y)
387 dirty(QRect(x, y, 1, 1));
391 void DrawingWindow::dirty(int x1, int y1, int x2, int y2)
394 r.setCoords(x1, y1, x2, y2);
395 dirty(r.normalized());
398 void DrawingWindow::dirty(const QRect &rect)
408 void DrawingWindow::mayUpdate()
411 bool dirty = dirtyFlag;
412 QRect rect = dirtyRect;
419 //--- DrawingThread ----------------------------------------------------
421 DrawingThread::DrawingThread(DrawingWindow &w, DrawingWindow::ThreadFunction f)
424 , started_once(false)
428 void DrawingThread::start_once(Priority priority)
436 void DrawingThread::run()
438 threadFunction(drawingWindow);