1 #include "DrawingWindow.h"
2 #include <QApplication>
8 class DrawingThread: public QThread {
10 DrawingThread(DrawingWindow &w, DrawingWindow::ThreadFunction f);
11 void start_once(Priority priority = InheritPriority);
17 DrawingWindow &drawingWindow;
18 DrawingWindow::ThreadFunction threadFunction;
21 friend class DrawingWindow;
24 //--- DrawingWindow ----------------------------------------------------
26 DrawingWindow::DrawingWindow(ThreadFunction f, int w, int h)
34 DrawingWindow::DrawingWindow(QWidget *parent,
35 ThreadFunction f, int w, int h)
43 DrawingWindow::DrawingWindow(QWidget *parent, Qt::WindowFlags flags,
44 ThreadFunction f, int w, int h)
45 : QWidget(parent, flags)
52 DrawingWindow::~DrawingWindow()
59 void DrawingWindow::setColor(float red, float green, float blue)
61 fgColor.setRgbF(red, green, blue);
65 void DrawingWindow::setColor(const char *name)
67 fgColor.setNamedColor(name);
71 void DrawingWindow::setBgColor(float red, float green, float blue)
73 bgColor.setRgbF(red, green, blue);
76 void DrawingWindow::setBgColor(const char *name)
78 bgColor.setNamedColor(name);
81 void DrawingWindow::clearGraph()
84 painter->fillRect(image->rect(), bgColor);
86 safeUnlock(imageMutex);
89 void DrawingWindow::drawPoint(int x, int y)
92 painter->drawPoint(x, y);
94 safeUnlock(imageMutex);
97 void DrawingWindow::drawLine(int x1, int y1, int x2, int y2)
100 painter->drawLine(x1, y1, x2, y2);
101 dirty(x1, y1, x2, y2);
102 safeUnlock(imageMutex);
105 void DrawingWindow::drawRect(int x1, int y1, int x2, int y2)
108 r.setCoords(x1, y1, x2 - 1, y2 - 1);
110 safeLock(imageMutex);
111 painter->drawRect(r);
112 r.adjust(0, 0, 1, 1);
114 safeUnlock(imageMutex);
117 void DrawingWindow::fillRect(int x1, int y1, int x2, int y2)
119 painter->setBrush(fgColor);
120 drawRect(x1, y1, x2, y2);
121 painter->setBrush(Qt::NoBrush);
124 void DrawingWindow::drawCircle(int x, int y, int r)
127 rect.setCoords(x - r, y - r, x + r - 1, y + r - 1);
128 safeLock(imageMutex);
129 painter->drawEllipse(rect);
130 rect.adjust(0, 0, 1, 1);
132 safeUnlock(imageMutex);
135 void DrawingWindow::fillCircle(int x, int y, int r)
137 painter->setBrush(fgColor);
139 painter->setBrush(Qt::NoBrush);
142 void DrawingWindow::drawText(int x, int y, const char *text)
144 QRect r(image->rect());
146 safeLock(imageMutex);
147 painter->drawText(r, 0, text, &r);
149 safeUnlock(imageMutex);
152 bool DrawingWindow::sync(unsigned long time)
156 if (terminateThread) {
159 qApp->postEvent(this, new QEvent(QEvent::User));
160 synced = syncCondition.wait(&syncMutex, time);
162 safeUnlock(syncMutex);
166 void DrawingWindow::closeGraph()
168 qApp->postEvent(this, new QEvent(QEvent::Type(QEvent::User + 1)));
171 void DrawingWindow::sleep(unsigned long secs)
173 DrawingThread::sleep(secs);
176 void DrawingWindow::msleep(unsigned long msecs)
178 DrawingThread::msleep(msecs);
181 void DrawingWindow::usleep(unsigned long usecs)
183 DrawingThread::usleep(usecs);
186 void DrawingWindow::closeEvent(QCloseEvent *ev)
191 terminateThread = true; // this flag is needed for the case
192 // where the following wakeAll() call
193 // occurs between the
194 // setTerminationEnable(false) and the
195 // mutex lock in safeLock() called
197 syncCondition.wakeAll();
199 QWidget::closeEvent(ev);
203 void DrawingWindow::customEvent(QEvent *ev)
205 switch ((int )ev->type()) {
208 qApp->sendPostedEvents(this, QEvent::UpdateLater);
209 qApp->sendPostedEvents(this, QEvent::UpdateRequest);
210 qApp->sendPostedEvents(this, QEvent::Paint);
211 qApp->processEvents(QEventLoop::ExcludeUserInputEvents |
212 QEventLoop::ExcludeSocketNotifiers |
213 QEventLoop::DeferredDeletion |
214 QEventLoop::X11ExcludeTimers);
218 syncCondition.wakeAll();
221 case QEvent::User + 1:
227 void DrawingWindow::keyPressEvent(QKeyEvent *ev)
242 void DrawingWindow::paintEvent(QPaintEvent *ev)
244 QPainter widgetPainter(this);
246 QImage imageCopy(*image);
248 QRect rect = ev->rect();
249 widgetPainter.drawImage(rect, imageCopy, rect);
252 void DrawingWindow::showEvent(QShowEvent *ev)
254 timer.start(paintInterval, this);
255 thread->start_once(QThread::IdlePriority);
256 QWidget::showEvent(ev);
259 void DrawingWindow::timerEvent(QTimerEvent *ev)
261 if (ev->timerId() == timer.timerId()) {
263 timer.start(paintInterval, this);
265 QWidget::timerEvent(ev);
269 //--- DrawingWindow (private methods) ----------------------------------
271 void DrawingWindow::initialize(DrawingWindow::ThreadFunction f)
273 terminateThread = false;
275 image = new QImage(width, height, QImage::Format_RGB32);
276 painter = new QPainter(image);
277 thread = new DrawingThread(*this, f);
279 setFocusPolicy(Qt::StrongFocus);
280 setFixedSize(image->size());
281 setAttribute(Qt::WA_OpaquePaintEvent);
292 void DrawingWindow::applyColor()
294 QPen pen(painter->pen());
295 pen.setColor(fgColor);
296 painter->setPen(pen);
300 void DrawingWindow::safeLock(QMutex &mutex)
302 if (lockCount++ == 0)
303 thread->setTerminationEnabled(false);
308 void DrawingWindow::safeUnlock(QMutex &mutex)
311 if (--lockCount == 0)
312 thread->setTerminationEnabled(true);
316 void DrawingWindow::dirty()
319 dirtyRect = image->rect();
323 void DrawingWindow::dirty(int x, int y)
325 dirty(QRect(x, y, 1, 1));
329 void DrawingWindow::dirty(int x1, int y1, int x2, int y2)
332 r.setCoords(x1, y1, x2, y2);
333 dirty(r.normalized());
336 void DrawingWindow::dirty(const QRect &rect)
346 void DrawingWindow::mayUpdate()
349 bool dirty = dirtyFlag;
350 QRect rect = dirtyRect;
357 //--- DrawingThread ----------------------------------------------------
359 DrawingThread::DrawingThread(DrawingWindow &w, DrawingWindow::ThreadFunction f)
362 , started_once(false)
366 void DrawingThread::start_once(Priority priority)
374 void DrawingThread::run()
376 threadFunction(drawingWindow);