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::sleep(unsigned long secs)
168 DrawingThread::sleep(secs);
171 void DrawingWindow::msleep(unsigned long msecs)
173 DrawingThread::msleep(msecs);
176 void DrawingWindow::usleep(unsigned long usecs)
178 DrawingThread::usleep(usecs);
181 void DrawingWindow::closeEvent(QCloseEvent *ev)
186 terminateThread = true; // this flag is needed for the case
187 // where the following wakeAll() call
188 // occurs between the
189 // setTerminationEnable(false) and the
190 // mutex lock in safeLock() called
192 syncCondition.wakeAll();
194 QWidget::closeEvent(ev);
198 void DrawingWindow::customEvent(QEvent *)
201 qApp->sendPostedEvents(this, QEvent::UpdateLater);
202 qApp->sendPostedEvents(this, QEvent::UpdateRequest);
203 qApp->sendPostedEvents(this, QEvent::Paint);
204 qApp->processEvents(QEventLoop::ExcludeUserInputEvents |
205 QEventLoop::ExcludeSocketNotifiers |
206 QEventLoop::DeferredDeletion |
207 QEventLoop::X11ExcludeTimers);
211 syncCondition.wakeAll();
215 void DrawingWindow::keyPressEvent(QKeyEvent *ev)
230 void DrawingWindow::paintEvent(QPaintEvent *ev)
232 QPainter widgetPainter(this);
234 QImage imageCopy(*image);
236 QRect rect = ev->rect();
237 widgetPainter.drawImage(rect, imageCopy, rect);
240 void DrawingWindow::showEvent(QShowEvent *ev)
242 timer.start(paintInterval, this);
243 thread->start_once(QThread::IdlePriority);
244 QWidget::showEvent(ev);
247 void DrawingWindow::timerEvent(QTimerEvent *ev)
249 if (ev->timerId() == timer.timerId()) {
251 timer.start(paintInterval, this);
253 QWidget::timerEvent(ev);
257 //--- DrawingWindow (private methods) ----------------------------------
259 void DrawingWindow::initialize(DrawingWindow::ThreadFunction f)
261 terminateThread = false;
263 image = new QImage(width, height, QImage::Format_RGB32);
264 painter = new QPainter(image);
265 thread = new DrawingThread(*this, f);
267 setFocusPolicy(Qt::StrongFocus);
268 setFixedSize(image->size());
269 setAttribute(Qt::WA_OpaquePaintEvent);
280 void DrawingWindow::applyColor()
282 QPen pen(painter->pen());
283 pen.setColor(fgColor);
284 painter->setPen(pen);
288 void DrawingWindow::safeLock(QMutex &mutex)
290 if (lockCount++ == 0)
291 thread->setTerminationEnabled(false);
296 void DrawingWindow::safeUnlock(QMutex &mutex)
299 if (--lockCount == 0)
300 thread->setTerminationEnabled(true);
304 void DrawingWindow::dirty()
307 dirtyRect = image->rect();
311 void DrawingWindow::dirty(int x, int y)
313 dirty(QRect(x, y, 1, 1));
317 void DrawingWindow::dirty(int x1, int y1, int x2, int y2)
320 r.setCoords(x1, y1, x2, y2);
321 dirty(r.normalized());
324 void DrawingWindow::dirty(const QRect &rect)
334 void DrawingWindow::mayUpdate()
337 bool dirty = dirtyFlag;
338 QRect rect = dirtyRect;
345 //--- DrawingThread ----------------------------------------------------
347 DrawingThread::DrawingThread(DrawingWindow &w, DrawingWindow::ThreadFunction f)
350 , started_once(false)
354 void DrawingThread::start_once(Priority priority)
362 void DrawingThread::run()
364 threadFunction(drawingWindow);