From: giersch Date: Thu, 22 Nov 2007 17:12:58 +0000 (+0000) Subject: . X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/graphlib.git/commitdiff_plain/e1e6264f7d64fc0fc64263e55099e6a993596520?hp=560e71cddf71dc432454f027fe20d55442e28ac9 . --- diff --git a/DrawingWindow.cpp b/DrawingWindow.cpp index 284aaea..6a4f56e 100644 --- a/DrawingWindow.cpp +++ b/DrawingWindow.cpp @@ -4,6 +4,8 @@ #include #include +/*! Classe de thread. + */ class DrawingThread: public QThread { public: DrawingThread(DrawingWindow &w, DrawingWindow::ThreadFunction f); @@ -21,66 +23,110 @@ private: }; enum UserEvents { - SyncRequest = QEvent::User, - CloseRequest, - DrawTextRequest, + SyncRequest = QEvent::User, //!< Demande de synchronisation. + CloseRequest, //!< Demande de fermeture de la fenêtre. + DrawTextRequest, //!< Demande d'écriture de texte. }; -namespace { - class SyncRequestEvent: public QEvent { - public: - SyncRequestEvent(): QEvent(static_cast(SyncRequest)) - { } - }; - - class CloseRequestEvent: public QEvent { - public: - CloseRequestEvent(): QEvent(static_cast(CloseRequest)) - { } - }; - - class DrawTextEvent: public QEvent { - public: - const int x; - const int y; - const char *text; - const int flags; - DrawTextEvent(int x_, int y_, const char* text_, int flags_) - : QEvent(static_cast(DrawTextRequest)) - , x(x_), y(y_), text(text_), flags(flags_) - { } - }; +/*! Demande de synchronisation. + */ +class SyncRequestEvent: public QEvent { +public: + SyncRequestEvent(): QEvent(static_cast(SyncRequest)) + { } +}; -} +/*! Demande de fermeture de fenêtre. + */ +class CloseRequestEvent: public QEvent { +public: + CloseRequestEvent(): QEvent(static_cast(CloseRequest)) + { } +}; + +/*! Demande de tracé de texte. + */ +class DrawTextEvent: public QEvent { +public: + const int x; + const int y; + const char *text; + const int flags; + DrawTextEvent(int x_, int y_, const char* text_, int flags_) + : QEvent(static_cast(DrawTextRequest)) + , x(x_), y(y_), text(text_), flags(flags_) + { } +}; //--- DrawingWindow ---------------------------------------------------- -DrawingWindow::DrawingWindow(ThreadFunction f, int w, int h) +/*! Constructeur. + * + * Construit une nouvelle fenêtre de dessin avec les dimensions + * passées en paramètres. La fonction fun sera exécutée dans un + * nouveau thread. + * + * \param fun fonction de dessin + * \param width_ largeur de la fenêtre + * \param height_ hauteur de la fenêtre + * + * \see QWidget + */ +DrawingWindow::DrawingWindow(ThreadFunction fun, int width_, int height_) : QWidget() - , width(w) - , height(h) -{ - initialize(f); -} - + , width(width_) + , height(height_) +{ + initialize(fun); +} + +/*! Constructeur. + * + * Construit un nouveau widget de dessin avec les dimensions passées + * en paramètres. La fonction fun sera exécutée dans un nouveau + * thread. + * + * \param parent widget parent + * \param fun fonction de dessin + * \param width_ largeur de la fenêtre + * \param height_ hauteur de la fenêtre + * + * \see QWidget + */ DrawingWindow::DrawingWindow(QWidget *parent, - ThreadFunction f, int w, int h) + ThreadFunction fun, int width_, int height_) : QWidget(parent) - , width(w) - , height(h) -{ - initialize(f); -} - + , width(width_) + , height(height_) +{ + initialize(fun); +} + +/*! Constructeur. + * + * Construit un nouveau widget de dessin avec les dimensions passées + * en paramètres. La fonction fun sera exécutée dans un nouveau + * thread. + * + * \param parent widget parent + * \param flags flags passés au constructeur de QWidget + * \param fun fonction de dessin + * \param width_ largeur de la fenêtre + * \param height_ hauteur de la fenêtre + * + * \see QWidget + */ DrawingWindow::DrawingWindow(QWidget *parent, Qt::WindowFlags flags, - ThreadFunction f, int w, int h) + ThreadFunction fun, int width_, int height_) : QWidget(parent, flags) - , width(w) - , height(h) + , width(width_) + , height(height_) { - initialize(f); + initialize(fun); } +/*! Destructeur. + */ DrawingWindow::~DrawingWindow() { delete thread; @@ -88,36 +134,104 @@ DrawingWindow::~DrawingWindow() delete image; } +/*! Change la couleur de dessin. + * + * La couleur est un entier, tel que retourné par getPointColor. + * Normalement de la forme #00RRGGBB. + * + * \param color couleur + * + * \see setColor(const char *), setColor(float, float, float), + * setBgColor(unsigned int), + * getPointColor + */ void DrawingWindow::setColor(unsigned int color) { setColor(QColor::fromRgb(color)); } +/*! Change la couleur de dessin. + * + * Le nom de couleur est de la forme "black", "white", "red", "blue", ... + * + * \param name nom de couleur + * + * \see setColor(unsigned int), setColor(float, float, float), + * setBgColor(const char *) + * \see http://www.w3.org/TR/SVG/types.html#ColorKeywords + */ void DrawingWindow::setColor(const char *name) { setColor(QColor(name)); } +/*! Change la couleur de dessin. + * + * Les composantes de rouge, vert et bleu de la couleur doivent être + * compris entre 0 et 1. Si le trois composantes sont à 0, on obtient + * du noir; si les trois composantes sont à 1, on obtient du blanc. + * + * \param red composante de rouge + * \param green composante de vert + * \param blue composante de bleu + * + * \see setColor(unsigned int), setColor(const char *), + * setBgColor(float, float, float) + */ void DrawingWindow::setColor(float red, float green, float blue) { setColor(QColor::fromRgbF(red, green, blue)); } +/*! Change la couleur de fond. + * + * \param color couleur + * + * \see setBgColor(const char *), setBgColor(float, float, float), + * setColor(unsigned int), + * getPointColor, + * clearGraph + */ void DrawingWindow::setBgColor(unsigned int color) { setBgColor(QColor::fromRgb(color)); } +/*! Change la couleur de fond. + * + * \param name nom de couleur + * + * \see setBgColor(unsigned int), setBgColor(float, float, float), + * setColor(const char *), + * clearGraph + * \see http://www.w3.org/TR/SVG/types.html#ColorKeywords + */ void DrawingWindow::setBgColor(const char *name) { setBgColor(QColor(name)); } +/*! Change la couleur de fond. + * + * \param red composante de rouge + * \param green composante de vert + * \param blue composante de bleu + * + * \see setBgColor(unsigned int), setBgColor(const char *), + * setColor(float, float, float), + * clearGraph + */ void DrawingWindow::setBgColor(float red, float green, float blue) { setBgColor(QColor::fromRgbF(red, green, blue)); } +/*! Efface la fenêtre. + * + * La fenêtre est effacée avec la couleur de fond courante. + * + * \see setBgColor + */ void DrawingWindow::clearGraph() { safeLock(imageMutex); @@ -126,6 +240,15 @@ void DrawingWindow::clearGraph() safeUnlock(imageMutex); } +/*! Dessine un point. + * + * Dessine un point (pixel) aux coordonnées (x, y), avec la couleur de + * dessin courante. + * + * \param x, y coordonnées du point + * + * \see setColor + */ void DrawingWindow::drawPoint(int x, int y) { safeLock(imageMutex); @@ -134,6 +257,16 @@ void DrawingWindow::drawPoint(int x, int y) safeUnlock(imageMutex); } +/*! Dessine un segment. + * + * Dessine un segement de droite entre les coordonnées (x1, y1) et + * (x2, y2), avec la couleur de dessin courante. + * + * \param x1, y1 coordonnées d'une extrémité du segment + * \param x2, y2 coordonnées de l'autre extrémité du segment + * + * \see setColor + */ void DrawingWindow::drawLine(int x1, int y1, int x2, int y2) { safeLock(imageMutex); @@ -142,6 +275,17 @@ void DrawingWindow::drawLine(int x1, int y1, int x2, int y2) safeUnlock(imageMutex); } +/*! Dessine un rectangle. + * + * Dessine le rectangle parallèle aux axes et défini par les + * coordonnées de deux sommets opposés (x1, y1) et (x2, y2). Utilise + * la couleur de dessin courante. + * + * \param x1, y1 coordonnées d'un sommet du rectangle + * \param x2, y2 coordonnées du sommet opposé du rectangle + * + * \see fillRect, setColor + */ void DrawingWindow::drawRect(int x1, int y1, int x2, int y2) { QRect r; @@ -154,6 +298,17 @@ void DrawingWindow::drawRect(int x1, int y1, int x2, int y2) safeUnlock(imageMutex); } +/*! Dessine un rectangle plein. + * + * Dessine le rectangle plein parallèle aux axes et défini par les + * coordonnées de deux sommets opposés (x1, y1) et (x2, y2). Utilise + * la couleur de dessin courante. + * + * \param x1, y1 coordonnées d'un sommet du rectangle + * \param x2, y2 coordonnées du sommet opposé du rectangle + * + * \see drawRect, setColor + */ void DrawingWindow::fillRect(int x1, int y1, int x2, int y2) { painter->setBrush(getColor()); @@ -161,6 +316,16 @@ void DrawingWindow::fillRect(int x1, int y1, int x2, int y2) painter->setBrush(Qt::NoBrush); } +/*! Dessine un cercle. + * + * Dessine un cercle de centre (x, y) et de rayon r. Utilise la + * couleur de dessin courante. + * + * \param x, y coordonnées du centre du cercle + * \param r rayon du cercle + * + * \see fillCircle, setColor + */ void DrawingWindow::drawCircle(int x, int y, int r) { QRect rect; @@ -172,6 +337,16 @@ void DrawingWindow::drawCircle(int x, int y, int r) safeUnlock(imageMutex); } +/*! Dessine un disque. + * + * Dessine un disque (cercle plein) de centre (x, y) et de rayon r. + * Utilise la couleur de dessin courante. + * + * \param x, y coordonnées du centre du disque + * \param r rayon du disque + * + * \see drawCircle, setColor + */ void DrawingWindow::fillCircle(int x, int y, int r) { painter->setBrush(getColor()); @@ -179,6 +354,22 @@ void DrawingWindow::fillCircle(int x, int y, int r) painter->setBrush(Qt::NoBrush); } +/*! Écrit du texte. + * + * Écrit le texte text, aux coordonnées (x, y) et avec les paramètres + * d'alignement flags. Le texte est écrit avec la couleur de dessin + * courante. Les flags sont une combinaison (ou binaire) de + * Qt::AlignLeft, Qt::AligneRight, Qt::AlignHCenter, Qt::AlignTop, + * Qt::AlignBottom, Qt::AlignVCenter, Qt::AlignCenter. Par défaut, le + * texte est aligné en haut à gauche. + * + * \param x, y coordonnées du texte + * \param text texte à écrire + * \param flags paramètres d'alignement + * + * \see drawTextBg, setColor + * \see QPainter::drawText + */ void DrawingWindow::drawText(int x, int y, const char *text, int flags) { safeLock(syncMutex); @@ -189,6 +380,17 @@ void DrawingWindow::drawText(int x, int y, const char *text, int flags) safeUnlock(syncMutex); } +/*! Écrit du texte sur fond coloré. + * + * Écrit du texte comme drawText, mais l'arrière-plan est coloré avec + * la couleur de fond courante. + * + * \param x, y coordonnées du texte + * \param text texte à écrire + * \param flags paramètres d'alignement + * + * \see drawText, setColor, setColorBg + */ void DrawingWindow::drawTextBg(int x, int y, const char *text, int flags) { painter->setBackgroundMode(Qt::OpaqueMode); @@ -196,11 +398,34 @@ void DrawingWindow::drawTextBg(int x, int y, const char *text, int flags) painter->setBackgroundMode(Qt::TransparentMode); } + +/*! Retourne la couleur d'un pixel. + * + * Retourne la couleur du pixel de coordonnées (x, y). La valeur + * retournée peut servir de paramètres à setColor(unsigned int) ou + * setBgColor(unsigned int). + * + * \param x, y coordonnées du pixel + * \return couleur du pixel + * + * \see setColor(unsigned int), setBgColor(unsigned int) + */ unsigned int DrawingWindow::getPointColor(int x, int y) { return image->pixel(x, y); } +/*! Synchronise le contenu de la fenêtre. + * + * Pour des raisons d'efficacités, le résultat des fonctions de dessin + * n'est pas affiché immédiatement. L'appel à sync permet de + * synchroniser le contenu de la fenêtre. Autrement dit, cela bloque + * l'exécution du programme jusqu'à ce que le contenu de la fenêtre + * soit à jour. + * + * \param time durée maximale de l'attente + * \return true si la fenêtre a pu être synchronisée + */ bool DrawingWindow::sync(unsigned long time) { bool synced; @@ -215,26 +440,42 @@ bool DrawingWindow::sync(unsigned long time) return synced; } +/*! Ferme la fenêtre graphique. + */ void DrawingWindow::closeGraph() { qApp->postEvent(this, new CloseRequestEvent()); } +/*! Suspend l'exécution pendant un certain temps. + * + * \param secs temps d'attente en seconde + */ void DrawingWindow::sleep(unsigned long secs) { DrawingThread::sleep(secs); } +/*! Suspend l'exécution pendant un certain temps. + * + * \param msecs temps d'attente en millisecondes + */ void DrawingWindow::msleep(unsigned long msecs) { DrawingThread::msleep(msecs); } +/*! Suspend l'exécution pendant un certain temps. + * + * \param usecs temps d'attente en microsecondes + */ void DrawingWindow::usleep(unsigned long usecs) { DrawingThread::usleep(usecs); } +/*! \see QWidget + */ void DrawingWindow::closeEvent(QCloseEvent *ev) { timer.stop(); @@ -252,6 +493,8 @@ void DrawingWindow::closeEvent(QCloseEvent *ev) thread->wait(); } +/*! \see QWidget + */ void DrawingWindow::customEvent(QEvent *ev) { switch ((int )ev->type()) { @@ -268,6 +511,8 @@ void DrawingWindow::customEvent(QEvent *ev) } } +/*! \see QWidget + */ void DrawingWindow::keyPressEvent(QKeyEvent *ev) { bool accept = true; @@ -283,6 +528,8 @@ void DrawingWindow::keyPressEvent(QKeyEvent *ev) ev->accept(); } +/*! \see QWidget + */ void DrawingWindow::paintEvent(QPaintEvent *ev) { QPainter widgetPainter(this); @@ -293,6 +540,8 @@ void DrawingWindow::paintEvent(QPaintEvent *ev) widgetPainter.drawImage(rect, imageCopy, rect); } +/*! \see QWidget + */ void DrawingWindow::showEvent(QShowEvent *ev) { QWidget::showEvent(ev); @@ -302,6 +551,8 @@ void DrawingWindow::showEvent(QShowEvent *ev) thread->start_once(QThread::IdlePriority); } +/*! \see QWidget + */ void DrawingWindow::timerEvent(QTimerEvent *ev) { if (ev->timerId() == timer.timerId()) { @@ -314,13 +565,19 @@ void DrawingWindow::timerEvent(QTimerEvent *ev) //--- DrawingWindow (private methods) ---------------------------------- -void DrawingWindow::initialize(DrawingWindow::ThreadFunction f) +/*! Fonction d'initialisation. + * + * Fonction appelée par les différents constructeurs. + * + * \param fun fonction de dessin + */ +void DrawingWindow::initialize(DrawingWindow::ThreadFunction fun) { terminateThread = false; lockCount = 0; image = new QImage(width, height, QImage::Format_RGB32); painter = new QPainter(image); - thread = new DrawingThread(*this, f); + thread = new DrawingThread(*this, fun); setFocusPolicy(Qt::StrongFocus); setFixedSize(image->size()); @@ -334,6 +591,10 @@ void DrawingWindow::initialize(DrawingWindow::ThreadFunction f) dirtyFlag = false; } +/*! Change la couleur de dessin. + * + * \param color couleur + */ inline void DrawingWindow::setColor(const QColor& color) { @@ -342,24 +603,45 @@ void DrawingWindow::setColor(const QColor& color) painter->setPen(pen); } +/*! Change la couleur de fond. + * + * \param color couleur + */ inline void DrawingWindow::setBgColor(const QColor& color) { painter->setBackground(color); } +/*! Retourne la couleur de dessin courante. + * + * \return couleur de dessin courante + */ inline QColor DrawingWindow::getColor() { return painter->pen().color(); } +/*! Retourne la couleur de fond courante. + * + * \return couleur de fond courante + */ inline QColor DrawingWindow::getBgColor() { return painter->background().color(); } +/*! Verrouille un mutex. + * + * S'assure que le thread courant ne peut pas être terminé s'il + * détient un mutex. Pendant de safeUnlock. + * + * \param mutex le mutex à verrouiller + * + * \see safeUnlock + */ inline void DrawingWindow::safeLock(QMutex &mutex) { @@ -368,6 +650,15 @@ void DrawingWindow::safeLock(QMutex &mutex) mutex.lock(); } +/*! Déverrouille un mutex. + * + * S'assure que le thread courant ne peut pas être terminé s'il + * détient un mutex. Pendant de safeLock. + * + * \param mutex le mutex à déverrouiller + * + * \see safeLock + */ inline void DrawingWindow::safeUnlock(QMutex &mutex) { @@ -376,6 +667,8 @@ void DrawingWindow::safeUnlock(QMutex &mutex) thread->setTerminationEnabled(true); } +/*! Marque l'image entière comme non à jour. + */ inline void DrawingWindow::dirty() { @@ -383,12 +676,24 @@ void DrawingWindow::dirty() dirtyRect = image->rect(); } +/*! Marque un point de l'image comme non à jour. + * + * \param x, y coordonnées du point + */ inline void DrawingWindow::dirty(int x, int y) { dirty(QRect(x, y, 1, 1)); } +/*! Marque une zone de l'image comme non à jour. + * + * La zone est définie par un rectangle dont les coordonnées de deux + * sommets oppposés sont données. + * + * \param x1, y1 coordonnées d'un sommet du rectangle + * \param x2, y2 coordonnées du sommet opposé du rectangle + */ inline void DrawingWindow::dirty(int x1, int y1, int x2, int y2) { @@ -397,6 +702,10 @@ void DrawingWindow::dirty(int x1, int y1, int x2, int y2) dirty(r.normalized()); } +/*! Marque une zone de l'image comme non à jour. + * + * \param rect rectangle délimitant la zone + */ void DrawingWindow::dirty(const QRect &rect) { if (dirtyFlag) { @@ -407,6 +716,11 @@ void DrawingWindow::dirty(const QRect &rect) } } +/*! Génère un update si besoin. + * + * Génère une demande de mise à jour de la fenêtre (appel à update) + * s'il y en a besoin. + */ void DrawingWindow::mayUpdate() { imageMutex.lock(); @@ -418,6 +732,12 @@ void DrawingWindow::mayUpdate() update(rect); } +/*! Fonction bas-niveau pour sync. + * + * Fonction de synchronisation dans le thread principal. + * + * \see sync, customEvent + */ void DrawingWindow::realSync() { mayUpdate(); @@ -435,6 +755,15 @@ void DrawingWindow::realSync() syncMutex.unlock(); } +/*! Fonction bas-niveau pour drawText. + * + * Le rendu de texte doit être fait dans le thread principal. D'où + * les manipulations tordues et la synchronisation qui s'en suit. + * + * \param x, y, text, flags cf. drawText + * + * \see drawText, customEvent + */ void DrawingWindow::realDrawText(int x, int y, const char *text, int flags) { QRect r(image->rect()); @@ -473,6 +802,8 @@ void DrawingWindow::realDrawText(int x, int y, const char *text, int flags) //--- DrawingThread ---------------------------------------------------- +/*! Constructeur. + */ DrawingThread::DrawingThread(DrawingWindow &w, DrawingWindow::ThreadFunction f) : drawingWindow(w) , threadFunction(f) @@ -480,6 +811,8 @@ DrawingThread::DrawingThread(DrawingWindow &w, DrawingWindow::ThreadFunction f) { } +/*! Démarre le thread si ce n'a pas encore été fait. + */ void DrawingThread::start_once(Priority priority) { if (!started_once) { @@ -488,6 +821,8 @@ void DrawingThread::start_once(Priority priority) } } +/*! La vraie fonction pour le thread. + */ void DrawingThread::run() { threadFunction(drawingWindow); diff --git a/DrawingWindow.h b/DrawingWindow.h index 97474e7..73fdc26 100644 --- a/DrawingWindow.h +++ b/DrawingWindow.h @@ -14,28 +14,36 @@ class DrawingThread; +/*! + * Fenêtre de dessin. + * + */ class DrawingWindow: public QWidget { public: + //! Type de la fonction de dessin, passée en paramètre de construction. typedef void (*ThreadFunction)(DrawingWindow &); + //! Largeur par défaut de la fenêtre. static const int DEFAULT_WIDTH = 640; + //! Hauteur par défaut de la fenêtre. static const int DEFAULT_HEIGHT = 480; DrawingWindow(ThreadFunction fun, - int width = DEFAULT_WIDTH, int height = DEFAULT_HEIGHT); + int width_ = DEFAULT_WIDTH, int height_ = DEFAULT_HEIGHT); DrawingWindow(QWidget *parent, ThreadFunction fun, - int width = DEFAULT_WIDTH, int height = DEFAULT_HEIGHT); + int width_ = DEFAULT_WIDTH, int height_ = DEFAULT_HEIGHT); DrawingWindow(QWidget *parent, Qt::WindowFlags flags, ThreadFunction fun, - int width = DEFAULT_WIDTH, int height = DEFAULT_HEIGHT); + int width_ = DEFAULT_WIDTH, int height_ = DEFAULT_HEIGHT); ~DrawingWindow(); + //! Largeur de la fenêtre. const int width; + //! Hauteur de la fenêtre. const int height; - // http://www.w3.org/TR/SVG/types.html#ColorKeywords void setColor(unsigned int color); void setColor(const char *name); void setColor(float red, float green, float blue); @@ -75,6 +83,7 @@ protected: void timerEvent(QTimerEvent *ev); private: + //! Intervalle de temps entre deux rendus (ms) static const int paintInterval = 33; QBasicTimer timer; @@ -92,7 +101,7 @@ private: DrawingThread *thread; - void initialize(ThreadFunction f); + void initialize(ThreadFunction fun); void setColor(const QColor& color); void setBgColor(const QColor& color); @@ -113,3 +122,7 @@ private: }; #endif // !DRAWING_WINDOW_H + +// Local variables: +// mode: c++ +// End: