Système de coordonnées
Le système de coordonnées est contrôlé par la classe QPainter. Avec les classes QPaintDevice et QPaintEngine, QPainter constitue la base du système de peinture de Qt, Arthur. QPainter est utilisée pour effectuer des opérations de dessin, QPaintDevice est une abstraction d'un espace bidimensionnel sur lequel on peut peindre à l'aide de QPainter, et QPaintEngine fournit l'interface que le peintre utilise pour dessiner sur différents types de périphériques.
La classe QPaintDevice est la classe de base des objets qui peuvent être peints : Les classes QWidget, QImage, QPixmap, QPicture et QOpenGLPaintDevice héritent de ses capacités de dessin. Le système de coordonnées par défaut d'un dispositif de peinture a son origine dans le coin supérieur gauche. Les valeurs x augmentent vers la droite et les valeurs y augmentent vers le bas. L'unité par défaut est le pixel pour les dispositifs basés sur les pixels et le point (1/72 de pouce) pour les imprimantes.
La correspondance entre les coordonnées logiques de QPainter et les coordonnées physiques de QPaintDevice est gérée par la matrice de transformation de QPainter, le point de vue et la "fenêtre". Les systèmes de coordonnées logiques et physiques coïncident par défaut. QPainter prend également en charge les transformations de coordonnées (par exemple, la rotation et la mise à l'échelle).
Rendu
Représentation logique
La taille (largeur et hauteur) d'une primitive graphique correspond toujours à son modèle mathématique, sans tenir compte de la largeur du stylo avec lequel elle est rendue :
| QRect(QPoint(1, 2), QPoint(7, 6)) | QLine(QPoint(2, 7), QPoint(6, 1)) |
| QLine(2, 7, 6, 1) | |
| QRect(QPoint(1, 2), QSize(6, 4)) | |
| QRect(1, 2, 6, 4) |
Peinture aliasée
Lors du dessin, le rendu des pixels est contrôlé par l'indice de rendu QPainter::Antialiasing.
L'énumération RenderHint est utilisée pour spécifier des drapeaux à QPainter qui peuvent être respectés ou non par un moteur donné. La valeur QPainter::Antialiasing indique que le moteur doit antialiaser les bords des primitives si possible, c'est-à-dire lisser les bords en utilisant des intensités de couleur différentes.
Mais par défaut, le peintre est aliasé et d'autres règles s'appliquent : Lors du rendu avec un stylo d'un pixel de large, les pixels seront rendus à droite et en dessous des points définis mathématiquement. Par exemple :
Lors du rendu avec un stylo d'un nombre pair de pixels, les pixels seront rendus symétriquement autour des points définis mathématiquement, tandis que lors du rendu avec un stylo d'un nombre impair de pixels, le pixel libre sera rendu à droite et en dessous du point mathématique comme dans le cas d'un pixel. Voir les diagrammes QRectF ci-dessous pour des exemples concrets.
| QRectF | |
|---|---|
![]() | ![]() |
| Représentation logique | Stylo d'une largeur d'un pixel |
![]() | ![]() |
| Stylo de deux pixels de large | Stylo de trois pixels de large |
Notez que pour des raisons historiques, la valeur de retour des fonctions QRect::right() et QRect::bottom() s'écarte du véritable coin inférieur droit du rectangle.
QRectEn effet, la fonction right() renvoie left() + width() - 1 et la fonction bottom() renvoie top() + height() - 1. Le point vert en bas à droite des diagrammes indique les coordonnées de retour de ces fonctions.
Nous vous recommandons d'utiliser QRectF à la place : La classe QRectF définit un rectangle dans le plan en utilisant des coordonnées en virgule flottante pour plus de précision (QRect utilise des coordonnées entières), et les fonctions QRectF::right() et QRectF::bottom() renvoient le véritable coin inférieur droit .
Il est également possible d'utiliser QRect, d'appliquer x() + width() et y() + height() pour trouver le coin inférieur droit et d'éviter les fonctions right() et bottom().
Peinture anticrénelée
Si vous définissez l'indice de rendu QPainter's anti-aliasing, les pixels seront rendus symétriquement de part et d'autre des points définis mathématiquement :
Transformations
Par défaut, le site QPainter utilise le système de coordonnées de l'appareil associé, mais il prend également en charge les transformations affines.
Vous pouvez mettre à l'échelle le système de coordonnées par un décalage donné en utilisant la fonction QPainter::scale(), vous pouvez le faire pivoter dans le sens des aiguilles d'une montre en utilisant la fonction QPainter::rotate() et vous pouvez le translater (c'est-à-dire ajouter un décalage donné aux points) en utilisant la fonction QPainter::translate().
Vous pouvez également faire pivoter le système de coordonnées autour de l'origine à l'aide de la fonction QPainter::shear(). Toutes les opérations de transformation opèrent sur la matrice de transformation de QPainter que vous pouvez récupérer à l'aide de la fonction QPainter::worldTransform(). Une matrice transforme un point du plan en un autre point.
Si vous avez besoin des mêmes transformations à plusieurs reprises, vous pouvez également utiliser les objets QTransform et les fonctions QPainter::worldTransform() et QPainter::setWorldTransform(). Vous pouvez à tout moment sauvegarder la matrice de transformation de QPainter en appelant la fonction QPainter::save() qui sauvegarde la matrice sur une pile interne. La fonction QPainter::restore() la récupère.
La matrice de transformation est souvent nécessaire lorsque l'on réutilise le même code de dessin sur différents dispositifs de peinture. Sans transformation, les résultats sont étroitement liés à la résolution du dispositif de peinture. Les imprimantes ont une résolution élevée, par exemple 600 points par pouce, alors que les écrans ont souvent une résolution comprise entre 72 et 100 points par pouce.
| Exemple d'horloge analogique | |
|---|---|
![]() | L'exemple de l'horloge analogique montre comment dessiner le contenu d'un widget personnalisé en utilisant la matrice de transformation de QPainter. Nous vous recommandons de compiler et d'exécuter cet exemple avant de poursuivre votre lecture. En particulier, essayez de redimensionner la fenêtre à différentes tailles. |
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()); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); painter.translate(width() / 2, height() / 2); painter.scale(side / 200.0, side / 200.0); Nous traduisons le système de coordonnées de sorte que le point (0, 0) se trouve au centre du widget, au lieu d'être dans le coin supérieur gauche. Nous mettons également le système à l'échelle de Cela nous donnera une zone carrée de 200 x 200, avec l'origine (0, 0) au centre, sur laquelle nous pourrons dessiner. Ce que nous dessinons s'affichera dans le plus grand carré possible qui tiendra dans le widget. Voir également la section Conversion fenêtre-portée de vue. {
QPainterStateGuard guard(&painter);
painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0)));
painter.drawConvexPolygon(hourHand, 4);
}Nous dessinons l'aiguille des heures de l'horloge en faisant pivoter le système de coordonnées et en appelant QPainter::drawConvexPolygon(). Grâce à la rotation, l'aiguille est dessinée dans la bonne direction. Le polygone est spécifié comme un tableau de valeurs x, y alternées, stockées dans la variable statique Les appels à QPainter::save() et QPainter::restore() qui entourent le code garantissent que le code qui suit ne sera pas perturbé par les transformations que nous avons utilisées. painter.setBrush(minuteColor); { QPainterStateGuard guard(&painter); painter.rotate(6.0 * time.minute()); painter.drawConvexPolygon(minuteHand, 4); } Ensuite, nous dessinons les marqueurs d'heure pour le cadran de l'horloge, qui consiste en douze lignes courtes à des intervalles de 30 degrés. Lorsque cette boucle est terminée, le peintre a effectué une rotation complète pour revenir à son état d'origine, nous n'avons donc pas besoin de sauvegarder et de restaurer l'état. {
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);
}Nous faisons de même pour l'aiguille des minutes de l'horloge, qui est définie par les trois points (7, 8), (-7, 8), (0, -70). Ces coordonnées indiquent une aiguille plus fine et plus longue que l'aiguille des minutes. for (int j = 0; j < 60; ++j) { painter.drawLine(92, 0, 96, 0); painter.rotate(6.0); } Enfin, nous dessinons les repères des minutes pour le cadran de l'horloge, qui consiste en soixante lignes courtes à des intervalles de 6 degrés. Nous sautons un repère des minutes sur cinq car nous ne voulons pas dessiner par-dessus les repères des heures. À la fin de cette étape, le peintre est tourné d'une manière qui n'est pas très utile, mais nous avons fini de peindre et cela n'a pas d'importance. | |
Pour plus d'informations sur la matrice de transformation, voir la documentation de QTransform.
Conversion fenêtre-portée de vue
Lorsque nous dessinons avec QPainter, nous spécifions des points à l'aide de coordonnées logiques qui sont ensuite converties en coordonnées physiques du dispositif de peinture.
worldTransform viewportLa conversion des coordonnées logiques en coordonnées physiques est gérée par la transformation du monde de QPainter() (décrite dans la section Transformations ) et par les transformations de QPainter() et window(). La fenêtre représente les coordonnées physiques en spécifiant un rectangle arbitraire. La "fenêtre" décrit le même rectangle en coordonnées logiques. Par défaut, les systèmes de coordonnées logiques et physiques coïncident et sont équivalents au rectangle du périphérique de peinture.
En utilisant la conversion fenêtre-vue, vous pouvez adapter le système de coordonnées logiques à vos préférences. Le mécanisme peut également être utilisé pour rendre le code de dessin indépendant du dispositif de peinture. Vous pouvez, par exemple, faire en sorte que les coordonnées logiques s'étendent de (-50, -50) à (50, 50) avec (0, 0) au centre en appelant la fonction QPainter::setWindow() :
Les coordonnées logiques (-50,-50) correspondent désormais aux coordonnées physiques du dispositif de peinture (0, 0). Indépendamment du dispositif de peinture, votre code de peinture fonctionnera toujours sur les coordonnées logiques spécifiées.
En définissant le rectangle de la "fenêtre" ou de la fenêtre de visualisation, vous effectuez une transformation linéaire des coordonnées. Notez que chaque coin de la "fenêtre" correspond au coin correspondant de la fenêtre de visualisation, et vice versa. C'est pourquoi il est normalement préférable que la fenêtre de visualisation et la "fenêtre" conservent le même rapport hauteur/largeur afin d'éviter toute déformation :
int side = qMin(width(), height()); int x = (width() - side / 2); int y = (height() - side / 2); painter.setViewport(x, y, side, side);
Si nous faisons en sorte que le système de coordonnées logiques soit un carré, nous devons également faire en sorte que la fenêtre soit un carré à l'aide de la fonction QPainter::setViewport(). Dans l'exemple ci-dessus, nous le rendons équivalent au plus grand carré pouvant entrer dans le rectangle du dispositif de peinture. En tenant compte de la taille du dispositif de peinture lors de la définition de la fenêtre ou de la fenêtre d'affichage, il est possible de maintenir le code de dessin indépendant du dispositif de peinture.
Notez que la conversion fenêtre-vue n'est qu'une transformation linéaire, c'est-à-dire qu'elle n'effectue pas d'écrêtage. Cela signifie que si vous peignez en dehors de la "fenêtre" actuellement définie, votre peinture est toujours transformée en fenêtre en utilisant la même approche algébrique linéaire.

La fenêtre de visualisation, la "fenêtre" et la matrice de transformation déterminent la manière dont les coordonnées logiques de QPainter correspondent aux coordonnées physiques du dispositif de peinture. Par défaut, la matrice de transformation du monde est la matrice d'identité, et les paramètres de la "fenêtre" et de la fenêtre de visualisation sont équivalents aux paramètres du dispositif de peinture, c'est-à-dire que les systèmes de coordonnées du monde, de la "fenêtre" et du dispositif sont équivalents, mais comme nous l'avons vu, les systèmes peuvent être manipulés à l'aide d'opérations de transformation et de conversion fenêtre-portée de visualisation. L'illustration ci-dessus décrit le processus.
Voir aussi Horloge analogique.
© 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.








