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;
24 SyncRequest = QEvent::User,
30 class SyncRequestEvent: public QEvent {
32 SyncRequestEvent(): QEvent(static_cast<QEvent::Type>(SyncRequest))
36 class CloseRequestEvent: public QEvent {
38 CloseRequestEvent(): QEvent(static_cast<QEvent::Type>(CloseRequest))
42 class DrawTextEvent: public QEvent {
48 DrawTextEvent(int x_, int y_, const char* text_, int flags_)
49 : QEvent(static_cast<QEvent::Type>(DrawTextRequest))
50 , x(x_), y(y_), text(text_), flags(flags_)
56 //--- DrawingWindow ----------------------------------------------------
58 DrawingWindow::DrawingWindow(ThreadFunction f, int w, int h)
66 DrawingWindow::DrawingWindow(QWidget *parent,
67 ThreadFunction f, int w, int h)
75 DrawingWindow::DrawingWindow(QWidget *parent, Qt::WindowFlags flags,
76 ThreadFunction f, int w, int h)
77 : QWidget(parent, flags)
84 DrawingWindow::~DrawingWindow()
91 void DrawingWindow::setColor(unsigned int color)
93 setColor(QColor::fromRgb(color));
96 void DrawingWindow::setColor(const char *name)
98 setColor(QColor(name));
101 void DrawingWindow::setColor(float red, float green, float blue)
103 setColor(QColor::fromRgbF(red, green, blue));
106 void DrawingWindow::setBgColor(unsigned int color)
108 setBgColor(QColor::fromRgb(color));
111 void DrawingWindow::setBgColor(const char *name)
113 setBgColor(QColor(name));
116 void DrawingWindow::setBgColor(float red, float green, float blue)
118 setBgColor(QColor::fromRgbF(red, green, blue));
121 void DrawingWindow::clearGraph()
123 safeLock(imageMutex);
124 painter->fillRect(image->rect(), getBgColor());
126 safeUnlock(imageMutex);
129 void DrawingWindow::drawPoint(int x, int y)
131 safeLock(imageMutex);
132 painter->drawPoint(x, y);
134 safeUnlock(imageMutex);
137 void DrawingWindow::drawLine(int x1, int y1, int x2, int y2)
139 safeLock(imageMutex);
140 painter->drawLine(x1, y1, x2, y2);
141 dirty(x1, y1, x2, y2);
142 safeUnlock(imageMutex);
145 void DrawingWindow::drawRect(int x1, int y1, int x2, int y2)
148 r.setCoords(x1, y1, x2 - 1, y2 - 1);
150 safeLock(imageMutex);
151 painter->drawRect(r);
152 r.adjust(0, 0, 1, 1);
154 safeUnlock(imageMutex);
157 void DrawingWindow::fillRect(int x1, int y1, int x2, int y2)
159 painter->setBrush(getColor());
160 drawRect(x1, y1, x2, y2);
161 painter->setBrush(Qt::NoBrush);
164 void DrawingWindow::drawCircle(int x, int y, int r)
167 rect.setCoords(x - r, y - r, x + r - 1, y + r - 1);
168 safeLock(imageMutex);
169 painter->drawEllipse(rect);
170 rect.adjust(0, 0, 1, 1);
172 safeUnlock(imageMutex);
175 void DrawingWindow::fillCircle(int x, int y, int r)
177 painter->setBrush(getColor());
179 painter->setBrush(Qt::NoBrush);
182 void DrawingWindow::drawText(int x, int y, const char *text, int flags)
185 if (!terminateThread) {
186 qApp->postEvent(this, new DrawTextEvent(x, y, text, flags));
187 syncCondition.wait(&syncMutex);
189 safeUnlock(syncMutex);
192 void DrawingWindow::drawTextBg(int x, int y, const char *text, int flags)
194 painter->setBackgroundMode(Qt::OpaqueMode);
195 drawText(x, y, text, flags);
196 painter->setBackgroundMode(Qt::TransparentMode);
199 unsigned int DrawingWindow::getPointColor(int x, int y)
201 return image->pixel(x, y);
204 bool DrawingWindow::sync(unsigned long time)
208 if (terminateThread) {
211 qApp->postEvent(this, new SyncRequestEvent());
212 synced = syncCondition.wait(&syncMutex, time);
214 safeUnlock(syncMutex);
218 void DrawingWindow::closeGraph()
220 qApp->postEvent(this, new CloseRequestEvent());
223 void DrawingWindow::sleep(unsigned long secs)
225 DrawingThread::sleep(secs);
228 void DrawingWindow::msleep(unsigned long msecs)
230 DrawingThread::msleep(msecs);
233 void DrawingWindow::usleep(unsigned long usecs)
235 DrawingThread::usleep(usecs);
238 void DrawingWindow::closeEvent(QCloseEvent *ev)
243 terminateThread = true; // this flag is needed for the case
244 // where the following wakeAll() call
245 // occurs between the
246 // setTerminationEnable(false) and the
247 // mutex lock in safeLock() called
249 syncCondition.wakeAll();
251 QWidget::closeEvent(ev);
255 void DrawingWindow::customEvent(QEvent *ev)
257 switch ((int )ev->type()) {
264 case DrawTextRequest:
265 DrawTextEvent* tev = dynamic_cast<DrawTextEvent *>(ev);
266 realDrawText(tev->x, tev->y, tev->text, tev->flags);
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 QWidget::showEvent(ev);
301 timer.start(paintInterval, this);
302 thread->start_once(QThread::IdlePriority);
305 void DrawingWindow::timerEvent(QTimerEvent *ev)
307 if (ev->timerId() == timer.timerId()) {
309 timer.start(paintInterval, this);
311 QWidget::timerEvent(ev);
315 //--- DrawingWindow (private methods) ----------------------------------
317 void DrawingWindow::initialize(DrawingWindow::ThreadFunction f)
319 terminateThread = false;
321 image = new QImage(width, height, QImage::Format_RGB32);
322 painter = new QPainter(image);
323 thread = new DrawingThread(*this, f);
325 setFocusPolicy(Qt::StrongFocus);
326 setFixedSize(image->size());
327 setAttribute(Qt::WA_OpaquePaintEvent);
338 void DrawingWindow::setColor(const QColor& color)
340 QPen pen(painter->pen());
342 painter->setPen(pen);
346 void DrawingWindow::setBgColor(const QColor& color)
348 painter->setBackground(color);
352 QColor DrawingWindow::getColor()
354 return painter->pen().color();
358 QColor DrawingWindow::getBgColor()
360 return painter->background().color();
364 void DrawingWindow::safeLock(QMutex &mutex)
366 if (lockCount++ == 0)
367 thread->setTerminationEnabled(false);
372 void DrawingWindow::safeUnlock(QMutex &mutex)
375 if (--lockCount == 0)
376 thread->setTerminationEnabled(true);
380 void DrawingWindow::dirty()
383 dirtyRect = image->rect();
387 void DrawingWindow::dirty(int x, int y)
389 dirty(QRect(x, y, 1, 1));
393 void DrawingWindow::dirty(int x1, int y1, int x2, int y2)
396 r.setCoords(x1, y1, x2, y2);
397 dirty(r.normalized());
400 void DrawingWindow::dirty(const QRect &rect)
410 void DrawingWindow::mayUpdate()
413 bool dirty = dirtyFlag;
414 QRect rect = dirtyRect;
421 void DrawingWindow::realSync()
424 qApp->sendPostedEvents(this, QEvent::UpdateLater);
425 qApp->sendPostedEvents(this, QEvent::UpdateRequest);
426 qApp->sendPostedEvents(this, QEvent::Paint);
427 qApp->processEvents(QEventLoop::ExcludeUserInputEvents |
428 QEventLoop::ExcludeSocketNotifiers |
429 QEventLoop::DeferredDeletion |
430 QEventLoop::X11ExcludeTimers);
434 syncCondition.wakeAll();
438 void DrawingWindow::realDrawText(int x, int y, const char *text, int flags)
440 QRect r(image->rect());
441 switch (flags & Qt::AlignHorizontal_Mask) {
445 case Qt::AlignHCenter:
447 r.setLeft(2 * x - width + 1);
454 switch (flags & Qt::AlignVertical_Mask) {
455 case Qt::AlignBottom:
458 case Qt::AlignVCenter:
460 r.setTop(2 * y - height + 1);
468 painter->drawText(r, flags, text, &r);
470 syncCondition.wakeAll();
474 //--- DrawingThread ----------------------------------------------------
476 DrawingThread::DrawingThread(DrawingWindow &w, DrawingWindow::ThreadFunction f)
479 , started_once(false)
483 void DrawingThread::start_once(Priority priority)
491 void DrawingThread::run()
493 threadFunction(drawingWindow);