Horloge analogique
L'exemple de l'horloge analogique montre comment dessiner le contenu d'un widget personnalisé.

Capture d'écran de l'exemple Horloge analogique
Cet exemple montre également comment les fonctions de transformation et de mise à l'échelle de QPainter peuvent être utilisées pour faciliter le dessin de widgets personnalisés.
Définition de la classe AnalogClock
La classe AnalogClock fournit un widget horloge avec les aiguilles des heures, des minutes et des secondes, qui est automatiquement mis à jour toutes les secondes. Nous sous-classons QWidget et réimplémentons la fonction standard paintEvent() pour dessiner le cadran de l'horloge :
class AnalogClock : public QWidget { Q_OBJECT public: AnalogClock(QWidget *parent = nullptr); protected: void paintEvent(QPaintEvent *event) override; };
Mise en œuvre de la classe AnalogClock
Lorsque le widget est construit, nous mettons en place un minuteur d'une seconde pour garder une trace de l'heure actuelle, et nous le connectons au slot standard update() afin que le cadran de l'horloge soit mis à jour lorsque le minuteur émet le signal timeout(). Enfin, nous redimensionnons le widget pour qu'il s'affiche à une taille raisonnable.
AnalogClock::AnalogClock(QWidget *parent) : QWidget(parent) { QTimer *timer = new QTimer(this); connect(timer, &QTimer::timeout, this, QOverload<>::of(&AnalogClock::update)); timer->start(1000); setWindowTitle(tr("Analog Clock")); resize(200, 200); }
La fonction paintEvent() est appelée chaque fois que le contenu du widget doit être mis à jour. Cela se produit lorsque le widget est affiché pour la première fois et lorsqu'il est couvert puis exposé, mais elle est également exécutée lorsque le slot update() du widget est appelé. Puisque nous avons connecté le signal timeout() du timer à ce slot, il sera appelé au moins une fois par seconde.
Avant de configurer le peintre et de dessiner l'horloge, nous définissons d'abord trois listes de QPoints et trois QColors qui seront utilisées pour les aiguilles des heures, des minutes et des secondes. Nous utilisons la fonction palette() pour obtenir des couleurs appropriées qui s'intègrent dans le reste de la fenêtre, à la fois en mode clair et en mode foncé. Les aiguilles des heures et des minutes sont dessinées dans la couleur d'avant-plan, l'aiguille des secondes est dessinée dans la couleur d'accentuation.
Nous déterminons également la longueur du côté le plus court du widget afin que le cadran de l'horloge puisse être placé à l'intérieur du widget. Il est également utile de déterminer l'heure actuelle avant de commencer à dessiner.
void AnalogClock::paintEvent(QPaintEvent *) { static const QPoint hourHand[4] = { QPoint(5, 14), QPoint(-5, 14), QPoint(-4, -71), QPoint(4, -71) }; static const QPoint minuteHand[4] = { QPoint(4, 14), QPoint(-4, 14), QPoint(-3, -89), QPoint(3, -89) }; static const QPoint secondsHand[4] = { QPoint(1, 14), QPoint(-1, 14), QPoint(-1, -89), QPoint(1, -89) }; const QColor hourColor(palette().color(QPalette::Text)); const QColor minuteColor(palette().color(QPalette::Text)); const QColor secondsColor(palette().color(QPalette::Accent)); int side = qMin(width(), height());
Le contenu des widgets personnalisés est dessiné à l'aide d'un QPainter. Les peintres peuvent être utilisés pour dessiner sur n'importe quel QPaintDevice, mais ils sont généralement utilisés avec les widgets, c'est pourquoi nous passons l'instance du widget au constructeur du peintre.
Nous appelons QPainter::setRenderHint() avec QPainter::Antialiasing pour activer l'anticrénelage. Cela rend le dessin des lignes diagonales beaucoup plus fluide.
painter.setRenderHint(QPainter::Antialiasing);
La translation déplace l'origine au centre du widget, et l'opération d'échelle garantit que les opérations de dessin suivantes sont mises à l'échelle pour s'adapter au widget. Nous utilisons un facteur d'échelle qui nous permet d'utiliser des coordonnées x et y comprises entre -100 et 100, et qui garantit que ces coordonnées sont comprises dans la longueur du côté le plus court du widget.
painter.translate(width() / 2, height() / 2); painter.scale(side / 200.0, side / 200.0);
Pour simplifier notre code, nous allons dessiner un cadran d'horloge de taille fixe qui sera positionné et mis à l'échelle de manière à ce qu'il se trouve au centre du widget.
Le peintre se charge de toutes les transformations effectuées lors de l'événement de peinture et s'assure que tout est dessiné correctement. Il est souvent plus facile de laisser le peintre gérer les transformations que d'effectuer des calculs manuels pour dessiner le contenu d'un widget personnalisé.

Nous réglons le stylo sur Qt::NoPen parce que nous ne voulons pas de contour, et nous utilisons un pinceau solide avec la couleur appropriée pour afficher les heures. Les pinceaux sont utilisés pour remplir des polygones et d'autres formes géométriques.
painter.setPen(Qt::NoPen); painter.setBrush(hourColor);
Nous dessinons d'abord l'aiguille des heures, en utilisant une formule qui fait pivoter le système de coordonnées dans le sens inverse des aiguilles d'une montre d'un nombre de degrés déterminé par l'heure et les minutes actuelles. Cela signifie que l'aiguille sera affichée avec une rotation dans le sens des aiguilles d'une montre de la valeur requise. Nous sauvegardons et restaurons la matrice de transformation avant et après la rotation en instanciant un site QPainterStateGuard, car nous voulons placer l'aiguille des minutes sans avoir à tenir compte des rotations précédentes.
{
QPainterStateGuard guard(&painter);
painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0)));
painter.drawConvexPolygon(hourHand, 4);
}Nous dessinons des marqueurs autour du bord de l'horloge pour chaque heure dans la même couleur que l'aiguille des heures. Nous dessinons chaque marqueur, puis nous faisons pivoter le système de coordonnées de manière à ce que le peintre soit prêt à recevoir le marqueur suivant.
for (int i = 0; i < 12; ++i) { painter.drawRect(73, -3, 16, 6); painter.rotate(30.0); }
L'aiguille des minutes est tournée et peinte de la même manière que l'aiguille des heures.
painter.setBrush(minuteColor); { QPainterStateGuard guard(&painter); painter.rotate(6.0 * time.minute()); painter.drawConvexPolygon(minuteHand, 4); }
Pour l'aiguille des secondes, nous procédons de la même manière et ajoutons deux cercles pour la mettre en valeur.
painter.setBrush(secondsColor); { QPainterStateGuard guard(&painter); painter.rotate(6.0 * time.second()); painter.drawConvexPolygon(secondsHand, 4); painter.drawEllipse(-3, -3, 6, 6); painter.drawEllipse(-5, -68, 10, 10); }
Enfin, nous dessinons des marqueurs autour du bord de l'horloge, pour indiquer les minutes et les secondes. Cette fois-ci, nous les dessinons comme des lignes et réglons donc le stylo sur la couleur correspondante.
painter.setPen(minuteColor); for (int j = 0; j < 60; ++j) { painter.drawLine(92, 0, 96, 0); painter.rotate(6.0); }
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.