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 bool DrawingWindow::sync(unsigned long time)
146 if (terminateThread) {
149 qApp->postEvent(this, new QEvent(QEvent::User));
150 synced = syncCondition.wait(&syncMutex, time);
152 safeUnlock(syncMutex);
156 void DrawingWindow::sleep(unsigned long secs)
158 DrawingThread::sleep(secs);
161 void DrawingWindow::msleep(unsigned long msecs)
163 DrawingThread::msleep(msecs);
166 void DrawingWindow::usleep(unsigned long usecs)
168 DrawingThread::usleep(usecs);
171 void DrawingWindow::closeEvent(QCloseEvent *ev)
176 terminateThread = true; // this flag is needed for the case
177 // where the following wakeAll() call
178 // occurs between the
179 // setTerminationEnable(false) and the
180 // mutex lock in safeLock() called
182 syncCondition.wakeAll();
184 QWidget::closeEvent(ev);
188 void DrawingWindow::customEvent(QEvent *)
191 qApp->sendPostedEvents(this, QEvent::UpdateLater);
192 qApp->sendPostedEvents(this, QEvent::UpdateRequest);
193 qApp->sendPostedEvents(this, QEvent::Paint);
194 qApp->processEvents(QEventLoop::ExcludeUserInputEvents |
195 QEventLoop::ExcludeSocketNotifiers |
196 QEventLoop::DeferredDeletion |
197 QEventLoop::X11ExcludeTimers);
201 syncCondition.wakeAll();
205 void DrawingWindow::keyPressEvent(QKeyEvent *ev)
220 void DrawingWindow::paintEvent(QPaintEvent *ev)
222 QPainter widgetPainter(this);
224 QImage imageCopy(*image);
226 QRect rect = ev->rect();
227 widgetPainter.drawImage(rect, imageCopy, rect);
230 void DrawingWindow::showEvent(QShowEvent *ev)
232 timer.start(paintInterval, this);
233 thread->start_once(QThread::IdlePriority);
234 QWidget::showEvent(ev);
237 void DrawingWindow::timerEvent(QTimerEvent *ev)
239 if (ev->timerId() == timer.timerId()) {
241 timer.start(paintInterval, this);
243 QWidget::timerEvent(ev);
247 //--- DrawingWindow (private methods) ----------------------------------
249 void DrawingWindow::initialize(DrawingWindow::ThreadFunction f)
251 terminateThread = false;
253 image = new QImage(width, height, QImage::Format_RGB32);
254 painter = new QPainter(image);
255 thread = new DrawingThread(*this, f);
257 setFocusPolicy(Qt::StrongFocus);
258 setFixedSize(image->size());
259 setAttribute(Qt::WA_OpaquePaintEvent);
270 void DrawingWindow::applyColor()
272 QPen pen(painter->pen());
273 pen.setColor(fgColor);
274 painter->setPen(pen);
278 void DrawingWindow::safeLock(QMutex &mutex)
280 if (lockCount++ == 0)
281 thread->setTerminationEnabled(false);
286 void DrawingWindow::safeUnlock(QMutex &mutex)
289 if (--lockCount == 0)
290 thread->setTerminationEnabled(true);
294 void DrawingWindow::dirty()
297 dirtyRect = image->rect();
301 void DrawingWindow::dirty(int x, int y)
303 dirty(QRect(x, y, 1, 1));
307 void DrawingWindow::dirty(int x1, int y1, int x2, int y2)
310 r.setCoords(x1, y1, x2, y2);
311 dirty(r.normalized());
314 void DrawingWindow::dirty(const QRect &rect)
324 void DrawingWindow::mayUpdate()
327 bool dirty = dirtyFlag;
328 QRect rect = dirtyRect;
335 //--- DrawingThread ----------------------------------------------------
337 DrawingThread::DrawingThread(DrawingWindow &w, DrawingWindow::ThreadFunction f)
340 , started_once(false)
344 void DrawingThread::start_once(Priority priority)
352 void DrawingThread::run()
354 threadFunction(drawingWindow);