Exemple de tracés de peinture
L'exemple « Painter Paths » montre comment utiliser les chemins de dessin pour créer des formes complexes destinées au rendu.

La classe « QPainterPath » fournit un conteneur pour les opérations de dessin, permettant de construire et de réutiliser des formes graphiques.
Un tracé de dessin est un objet composé d'un certain nombre d'éléments graphiques de base (tels que des rectangles, des ellipses, des lignes et des courbes), et peut être utilisé pour le remplissage, le contour et le découpage. Le principal avantage des chemins de dessin par rapport aux opérations de dessin classiques réside dans le fait que les formes complexes ne doivent être créées qu’une seule fois, mais qu’elles peuvent être dessinées à plusieurs reprises en appelant simplement la méthode QPainter::drawPath().
L’exemple se compose de deux classes :
- La classe `
RenderArea`, qui est un widget personnalisé affichant un seul tracé de dessin. - La classe `
Window`, qui est la fenêtre principale de l’application affichant plusieurs widgets `RenderArea` et permettant à l’utilisateur de manipuler le remplissage, le stylo, la couleur et l’angle de rotation des chemins de dessin.
Nous allons d'abord passer en revue la classe « Window », puis nous nous intéresserons à la classe « RenderArea ».
Définition de la classe Window
La classe ` Window ` hérite de ` QWidget` ; il s'agit de la fenêtre principale de l'application qui affiche plusieurs widgets ` RenderArea ` et permet à l'utilisateur de modifier le remplissage, le stylo, la couleur et l'angle de rotation des tracés du peintre.
class Window : public QWidget
{
Q_OBJECT
public:
Window();
private slots:
void fillRuleChanged();
void fillGradientChanged();
void penColorChanged();Nous déclarons trois slots privés pour répondre aux actions de l'utilisateur concernant le remplissage et la couleur : ` fillRuleChanged()`, ` fillGradientChanged() ` et ` penColorChanged()`.
Lorsque l’utilisateur modifie la largeur du stylo et l’angle de rotation, la nouvelle valeur est transmise directement aux widgets RenderArea à l’aide du signal QSpinBox::valueChanged(). La raison pour laquelle nous devons implémenter des slots pour mettre à jour le remplissage et la couleur est que QComboBox ne fournit pas de signal similaire transmettant la nouvelle valeur en argument ; nous devons donc récupérer la ou les nouvelles valeurs avant de pouvoir mettre à jour les widgets RenderArea.
private:
void populateWithColors(QComboBox *comboBox);
QVariant currentItemData(QComboBox *comboBox);Nous déclarons également deux fonctions privées pratiques : ` populateWithColors() ` remplit une ` QComboBox ` donnée avec des éléments correspondant aux noms de couleurs reconnus par Qt, et ` currentItemData() ` renvoie l’élément actuel d’une ` QComboBox` donnée.
QList<RenderArea*> renderAreas;
QLabel *fillRuleLabel;
QLabel *fillGradientLabel;
QLabel *fillToLabel;
QLabel *penWidthLabel;
QLabel *penColorLabel;
QLabel *rotationAngleLabel;
QComboBox *fillRuleComboBox;
QComboBox *fillColor1ComboBox;
QComboBox *fillColor2ComboBox;
QSpinBox *penWidthSpinBox;
QComboBox *penColorComboBox;
QSpinBox *rotationAngleSpinBox;
};Ensuite, nous déclarons les différents composants du widget de la fenêtre principale. Nous déclarons également une constante de commodité spécifiant le nombre de widgets RenderArea.
Implémentation de la classe Window
Dans le constructeur de Window, nous définissons les différents chemins de dessin et créons les widgets RenderArea correspondants qui permettront de dessiner les formes graphiques :
Window::Window()
{
QPainterPath rectPath;
rectPath.moveTo(20.0, 30.0);
rectPath.lineTo(80.0, 30.0);
rectPath.lineTo(80.0, 70.0);
rectPath.lineTo(20.0, 70.0);
rectPath.closeSubpath();Nous construisons un rectangle aux angles vifs à l’aide des fonctions ` QPainterPath::moveTo()` et ` QPainterPath::lineTo()`.
QPainterPath::moveTo() déplace le point courant vers le point passé en argument. Un chemin de dessin est un objet composé d’un certain nombre d’éléments graphiques, c’est-à-dire de sous-chemins. Le déplacement du point courant déclenche également un nouveau sous-chemin (ce qui ferme implicitement le chemin précédemment actif lorsque le nouveau est lancé). La fonction QPainterPath::lineTo() ajoute une ligne droite reliant le point courant au point d'arrivée donné. Une fois la ligne tracée, le point courant est mis à jour pour se situer au point d'arrivée de la ligne.
Nous déplaçons d’abord le point courant pour démarrer un nouveau sous-trajet, puis nous traçons trois des côtés du rectangle. Ensuite, nous appelons la fonction ` QPainterPath::closeSubpath()` qui trace une ligne jusqu’au début du sous-trajet courant. Un nouveau sous-trajet est automatiquement lancé lorsque le sous-trajet courant est fermé. Le point courant du nouveau tracé est (0, 0). Nous aurions également pu appeler ` QPainterPath::lineTo()` pour tracer la dernière ligne, puis démarrer explicitement un nouveau sous-trajet à l’aide de la fonction ` QPainterPath::moveTo()`.
QPainterPath fournit également la fonction de commodité QPainterPath::addRect(), qui ajoute un rectangle donné au tracé en tant que sous-tracé fermé. Le rectangle est ajouté sous la forme d’un ensemble de lignes dans le sens des aiguilles d’une montre. La position actuelle du tracé de dessin après l’ajout du rectangle se trouve au coin supérieur gauche de celui-ci.
QPainterPath roundRectPath;
roundRectPath.moveTo(80.0, 35.0);
roundRectPath.arcTo(70.0, 30.0, 10.0, 10.0, 0.0, 90.0);
roundRectPath.lineTo(25.0, 30.0);
roundRectPath.arcTo(20.0, 30.0, 10.0, 10.0, 90.0, 90.0);
roundRectPath.lineTo(20.0, 65.0);
roundRectPath.arcTo(20.0, 60.0, 10.0, 10.0, 180.0, 90.0);
roundRectPath.lineTo(75.0, 70.0);
roundRectPath.arcTo(70.0, 60.0, 10.0, 10.0, 270.0, 90.0);
roundRectPath.closeSubpath();Nous construisons ensuite un rectangle aux coins arrondis. Comme précédemment, nous utilisons les fonctions QPainterPath::moveTo() et QPainterPath::lineTo() pour tracer les côtés du rectangle. Pour créer les coins arrondis, nous utilisons la fonction QPainterPath::arcTo().
QPainterPath::arcTo() crée un arc qui occupe le rectangle donné (spécifié par un QRect ou par les coordonnées du rectangle), en partant de l'angle de départ donné et en s'étendant sur le nombre de degrés indiqué dans le sens antihoraire. Les angles sont exprimés en degrés. Les arcs dans le sens des aiguilles d’une montre peuvent être spécifiés à l’aide d’angles négatifs. La fonction relie le point courant au point de départ de l’arc s’ils ne sont pas déjà reliés.
QPainterPath ellipsePath;
ellipsePath.moveTo(80.0, 50.0);
ellipsePath.arcTo(20.0, 30.0, 60.0, 40.0, 0.0, 360.0);Nous utilisons également la fonction ` QPainterPath::arcTo()` pour construire le tracé de l’ellipse. Nous commençons par déplacer le point courant pour démarrer un nouveau tracé. Ensuite, nous appelons ` QPainterPath::arcTo()` avec un angle de départ de 0,0 et 360,0 degrés comme dernier argument, ce qui crée une ellipse.
Là encore, ` QPainterPath ` fournit une fonction pratique (` QPainterPath::addEllipse())` qui crée une ellipse à l’intérieur d’un rectangle de délimitation donné et l’ajoute au tracé du peintre. Si le sous-tracé actuel est fermé, un nouveau sous-tracé est lancé. L’ellipse est composée d’une courbe dans le sens des aiguilles d’une montre, commençant et se terminant à zéro degré (position 3 heures).
QPainterPath piePath;
piePath.moveTo(50.0, 50.0);
piePath.arcTo(20.0, 30.0, 60.0, 40.0, 60.0, 240.0);
piePath.closeSubpath();Lors de la construction du tracé du diagramme circulaire, nous continuons à utiliser une combinaison des fonctions mentionnées : nous déplaçons d’abord le point courant, ce qui lance un nouveau sous-tracé. Ensuite, nous créons une ligne reliant le centre du diagramme à l’arc, puis l’arc lui-même. Lorsque nous fermons le sous-tracé, nous construisons implicitement la dernière ligne revenant vers le centre du diagramme.
QPainterPath polygonPath;
polygonPath.moveTo(10.0, 80.0);
polygonPath.lineTo(20.0, 10.0);
polygonPath.lineTo(80.0, 30.0);
polygonPath.lineTo(90.0, 70.0);
polygonPath.closeSubpath();La construction d’un polygone équivaut à celle d’un rectangle.
QPainterPath La fonction pratique ` QPainterPath::addPolygon()` permet également d’ajouter le polygone donné au tracé en tant que nouveau sous-tracé. La position actuelle après l’ajout du polygone correspond au dernier point de celui-ci.
QPainterPath groupPath;
groupPath.moveTo(60.0, 40.0);
groupPath.arcTo(20.0, 20.0, 40.0, 40.0, 0.0, 360.0);
groupPath.moveTo(40.0, 40.0);
groupPath.lineTo(40.0, 80.0);
groupPath.lineTo(80.0, 80.0);
groupPath.lineTo(80.0, 40.0);
groupPath.closeSubpath();Nous créons ensuite un tracé composé d’un groupe de sous-tracés : nous déplaçons d’abord le point courant, puis créons un cercle à l’aide de la fonction QPainterPath::arcTo() avec un angle de départ de 0,0 et 360 degrés comme dernier argument, comme nous l’avons fait lors de la création du tracé en forme d’ellipse. Ensuite, nous déplaçons à nouveau le point courant, ce qui marque le début d’un nouveau sous-tracé, et construisons trois côtés d’un carré à l’aide de la fonction QPainterPath::lineTo().
À présent, lorsque nous appelons la fonction ` QPainterPath::closeSubpath()`, le dernier côté est créé. Rappelez-vous que la fonction ` QPainterPath::closeSubpath()` trace une ligne jusqu’au début du sous-trajet actuel, c’est-à-dire le carré.
QPainterPath Fournissons une fonction de commodité, ` QPainterPath::addPath()`, qui ajoute un chemin donné au chemin qui appelle la fonction.
QPainterPath textPath;
QFont timesFont("Times", 50);
timesFont.setStyleStrategy(QFont::ForceOutline);
textPath.addText(10, 70, timesFont, tr("Qt"));Lors de la création du tracé de texte, nous créons d’abord la police. Ensuite, nous définissons la stratégie de style de la police, qui indique à l’algorithme de correspondance des polices quel type de polices doit être utilisé pour trouver une famille par défaut appropriée. La fonction ` QFont::ForceOutline ` impose l’utilisation de polices vectorielles.
Pour construire le texte, nous utilisons la fonction QPainterPath::addText() qui ajoute le texte donné au tracé sous la forme d’un ensemble de sous-tracés fermés créés à partir de la police fournie. Les sous-tracés sont positionnés de manière à ce que l’extrémité gauche de la ligne de base du texte se trouve au point spécifié.
QPainterPath bezierPath;
bezierPath.moveTo(20, 30);
bezierPath.cubicTo(80, 0, 50, 50, 80, 80);Pour créer le tracé de Bézier, nous utilisons la fonction ` QPainterPath::cubicTo()` qui ajoute une courbe de Bézier entre le point courant et le point d'extrémité donné, avec le point de contrôle indiqué. Une fois la courbe ajoutée, le point courant est mis à jour pour se situer à l'extrémité de la courbe.
Dans ce cas, nous omettons de fermer le sous-trajet afin de n’avoir qu’une simple courbe. Il existe toutefois toujours une ligne logique reliant le point d’extrémité de la courbe au début du sous-trajet ; celle-ci devient visible lors du remplissage du trajet, comme on peut le voir dans la fenêtre principale de l’application.
QPainterPath starPath;
starPath.moveTo(90, 50);
for (int i = 1; i < 5; ++i) {
starPath.lineTo(50 + 40 * std::cos(0.8 * i * M_PI),
50 + 40 * std::sin(0.8 * i * M_PI));
}
starPath.closeSubpath();Le tracé final que nous construisons montre qu’il est possible d’utiliser QPainterPath pour créer des formes assez complexes en utilisant uniquement les fonctions QPainterPath::moveTo(), QPainterPath::lineTo() et QPainterPath::closeSubpath() mentionnées précédemment.
renderAreas.push_back(new RenderArea(rectPath));
renderAreas.push_back(new RenderArea(roundRectPath));
renderAreas.push_back(new RenderArea(ellipsePath));
renderAreas.push_back(new RenderArea(piePath));
renderAreas.push_back(new RenderArea(polygonPath));
renderAreas.push_back(new RenderArea(groupPath));
renderAreas.push_back(new RenderArea(textPath));
renderAreas.push_back(new RenderArea(bezierPath));
renderAreas.push_back(new RenderArea(starPath));Maintenant que nous avons créé tous les chemins de dessin dont nous avons besoin, nous créons un widget RenderArea correspondant pour chacun d’entre eux. Enfin, nous nous assurons que le nombre de zones de rendu est correct à l’aide de la macro Q_ASSERT().
fillRuleComboBox = new QComboBox;
fillRuleComboBox->addItem(tr("Odd Even"), Qt::OddEvenFill);
fillRuleComboBox->addItem(tr("Winding"), Qt::WindingFill);
fillRuleLabel = new QLabel(tr("Fill &Rule:"));
fillRuleLabel->setBuddy(fillRuleComboBox);Nous créons ensuite les widgets associés à la règle de remplissage des chemins de dessin.
Deux règles de remplissage sont disponibles dans Qt : La règle « Qt::OddEvenFill » détermine si un point se trouve à l’intérieur de la forme en traçant une ligne horizontale depuis ce point vers un emplacement situé à l’extérieur de la forme, puis en comptant le nombre d’intersections. Si ce nombre est impair, le point se trouve à l’intérieur de la forme. Il s’agit de la règle par défaut.
La règle « Qt::WindingFill » détermine si un point se trouve à l’intérieur de la forme en traçant une ligne horizontale depuis ce point vers un emplacement situé à l’extérieur de la forme. Elle détermine ensuite si la direction de la ligne à chaque point d’intersection est vers le haut ou vers le bas. Le nombre de boucles est déterminé en additionnant la direction de chaque intersection. Si ce nombre est différent de zéro, le point se trouve à l’intérieur de la forme.
La règle « Qt::WindingFill » peut, dans la plupart des cas, être considérée comme l’intersection de formes fermées.
fillColor1ComboBox = new QComboBox;
populateWithColors(fillColor1ComboBox);
fillColor1ComboBox->setCurrentIndex(fillColor1ComboBox->findText("mediumslateblue"));
fillColor2ComboBox = new QComboBox;
populateWithColors(fillColor2ComboBox);
fillColor2ComboBox->setCurrentIndex(fillColor2ComboBox->findText("cornsilk"));
fillGradientLabel = new QLabel(tr("&Fill Gradient:"));
fillGradientLabel->setBuddy(fillColor1ComboBox);
fillToLabel = new QLabel(tr("to"));
fillToLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
penWidthSpinBox = new QSpinBox;
penWidthSpinBox->setRange(0, 20);
penWidthLabel = new QLabel(tr("&Pen Width:"));
penWidthLabel->setBuddy(penWidthSpinBox);
penColorComboBox = new QComboBox;
populateWithColors(penColorComboBox);
penColorComboBox->setCurrentIndex(penColorComboBox->findText("darkslateblue"));
penColorLabel = new QLabel(tr("Pen &Color:"));
penColorLabel->setBuddy(penColorComboBox);
rotationAngleSpinBox = new QSpinBox;
rotationAngleSpinBox->setRange(0, 359);
rotationAngleSpinBox->setWrapping(true);
rotationAngleSpinBox->setSuffix(QLatin1String("\xB0"));
rotationAngleLabel = new QLabel(tr("&Rotation Angle:"));
rotationAngleLabel->setBuddy(rotationAngleSpinBox);Nous créons également les autres widgets associés au remplissage, au stylo et à l’angle de rotation.
connect(fillRuleComboBox, &QComboBox::activated,
this, &Window::fillRuleChanged);
connect(fillColor1ComboBox, &QComboBox::activated,
this, &Window::fillGradientChanged);
connect(fillColor2ComboBox, &QComboBox::activated,
this, &Window::fillGradientChanged);
connect(penColorComboBox, &QComboBox::activated,
this, &Window::penColorChanged);
for (RenderArea *area : std::as_const(renderAreas)) {
connect(penWidthSpinBox, &QSpinBox::valueChanged,
area, &RenderArea::setPenWidth);
connect(rotationAngleSpinBox, &QSpinBox::valueChanged,
area, &RenderArea::setRotationAngle);
}Nous connectons les signaux activated() des listes déroulantes aux slots associés de la classe Window, tandis que nous connectons le signal valueChanged() des champs de saisie directement aux slots respectifs du widget RenderArea.
QGridLayout *topLayout = new QGridLayout;
int i = 0;
for (RenderArea *area : std::as_const(renderAreas)) {
topLayout->addWidget(area, i / 3, i % 3);
++i;
}
QGridLayout *mainLayout = new QGridLayout;
mainLayout->addLayout(topLayout, 0, 0, 1, 4);
mainLayout->addWidget(fillRuleLabel, 1, 0);
mainLayout->addWidget(fillRuleComboBox, 1, 1, 1, 3);
mainLayout->addWidget(fillGradientLabel, 2, 0);
mainLayout->addWidget(fillColor1ComboBox, 2, 1);
mainLayout->addWidget(fillToLabel, 2, 2);
mainLayout->addWidget(fillColor2ComboBox, 2, 3);
mainLayout->addWidget(penWidthLabel, 3, 0);
mainLayout->addWidget(penWidthSpinBox, 3, 1, 1, 3);
mainLayout->addWidget(penColorLabel, 4, 0);
mainLayout->addWidget(penColorComboBox, 4, 1, 1, 3);
mainLayout->addWidget(rotationAngleLabel, 5, 0);
mainLayout->addWidget(rotationAngleSpinBox, 5, 1, 1, 3);
setLayout(mainLayout);Nous ajoutons les widgets RenderArea à une mise en page distincte que nous intégrons ensuite à la mise en page principale avec le reste des widgets.
fillRuleChanged();
fillGradientChanged();
penColorChanged();
penWidthSpinBox->setValue(2);
setWindowTitle(tr("Painter Paths"));
}Enfin, nous initialisons les widgets « RenderArea » en appelant les slots « fillRuleChanged() », « fillGradientChanged() » et « penColorChanged() », puis nous définissons la largeur initiale du stylo et le titre de la fenêtre.
void Window::fillRuleChanged()
{
Qt::FillRule rule = (Qt::FillRule)currentItemData(fillRuleComboBox).toInt();
for (RenderArea *area : std::as_const(renderAreas))
area->setFillRule(rule);
}
void Window::fillGradientChanged()
{
QColor color1 = qvariant_cast<QColor>(currentItemData(fillColor1ComboBox));
QColor color2 = qvariant_cast<QColor>(currentItemData(fillColor2ComboBox));
for (RenderArea *area : std::as_const(renderAreas))
area->setFillGradient(color1, color2);
}
void Window::penColorChanged()
{
QColor color = qvariant_cast<QColor>(currentItemData(penColorComboBox));
for (RenderArea *area : std::as_const(renderAreas))
area->setPenColor(color);
}Les slots privés sont implémentés pour récupérer la ou les nouvelles valeurs à partir des listes déroulantes associées et mettre à jour les widgets de la RenderArea.
Nous déterminons d’abord la ou les nouvelles valeurs à l’aide de la fonction privée ` currentItemData() ` et de la fonction modèle ` qvariant_cast()`. Ensuite, nous appelons le slot associé à chacun des widgets ` RenderArea ` afin de mettre à jour les tracés de dessin.
void Window::populateWithColors(QComboBox *comboBox)
{
const QStringList colorNames = QColor::colorNames();
for (const QString &name : colorNames)
comboBox->addItem(name, QColor(name));
}La fonction populateWithColors() remplit la liste déroulante donnée avec des éléments correspondant aux noms de couleurs reconnus par Qt, fournis par la fonction statique QColor::colorNames().
QVariant Window::currentItemData(QComboBox *comboBox)
{
return comboBox->itemData(comboBox->currentIndex());
}La fonction ` currentItemData() ` renvoie simplement l’élément actuel de la liste déroulante donnée.
Définition de la classe RenderArea
La classe ` RenderArea ` hérite de ` QWidget` et est un widget personnalisé affichant un seul tracé de dessin.
class RenderArea : public QWidget
{
Q_OBJECT
public:
explicit RenderArea(const QPainterPath &path, QWidget *parent = nullptr);
QSize minimumSizeHint() const override;
QSize sizeHint() const override;
public slots:
void setFillRule(Qt::FillRule rule);
void setFillGradient(const QColor &color1, const QColor &color2);
void setPenWidth(int width);
void setPenColor(const QColor &color);
void setRotationAngle(int degrees);
protected:
void paintEvent(QPaintEvent *event) override;Nous déclarons plusieurs slots publics permettant de mettre à jour le tracé de dessin associé au widget ` RenderArea `. De plus, nous réimplémentons les fonctions ` QWidget::minimumSizeHint()` et ` QWidget::sizeHint()` afin de donner au widget ` RenderArea ` une taille raisonnable au sein de notre application, et nous réimplémentons le gestionnaire d'événements ` QWidget::paintEvent()` pour dessiner son tracé de dessin.
private:
QPainterPath path;
QColor fillColor1;
QColor fillColor2;
int penWidth;
QColor penColor;
int rotationAngle;
};Chaque instance de la classe ` RenderArea ` possède un ` QPainterPath`, deux couleurs de remplissage, une largeur de stylo, une couleur de stylo et un angle de rotation.
Implémentation de la classe RenderArea
Le constructeur prend une instance de ` QPainterPath ` en argument (en plus du parent ` QWidget ` facultatif) :
RenderArea::RenderArea(const QPainterPath &path, QWidget *parent)
: QWidget(parent), path(path)
{
penWidth = 1;
rotationAngle = 0;
setBackgroundRole(QPalette::Base);
}Dans le constructeur, nous initialisons le widget « RenderArea » avec le paramètre « QPainterPath », tout en définissant la largeur du stylo et l’angle de rotation. Nous définissons également la couleur de remplissage du widget ( background role) ; la couleur de contour ( QPalette::Base ) est généralement blanche.
QSize RenderArea::minimumSizeHint() const
{
return QSize(50, 50);
}
QSize RenderArea::sizeHint() const
{
return QSize(100, 100);
}Ensuite, nous réimplémentons les fonctions ` QWidget::minimumSizeHint()` et ` QWidget::sizeHint()` afin de donner au widget ` RenderArea ` une taille raisonnable au sein de notre application.
void RenderArea::setFillRule(Qt::FillRule rule)
{
path.setFillRule(rule);
update();
}
void RenderArea::setFillGradient(const QColor &color1, const QColor &color2)
{
fillColor1 = color1;
fillColor2 = color2;
update();
}
void RenderArea::setPenWidth(int width)
{
penWidth = width;
update();
}
void RenderArea::setPenColor(const QColor &color)
{
penColor = color;
update();
}
void RenderArea::setRotationAngle(int degrees)
{
rotationAngle = degrees;
update();
}Les différents slots publics mettent à jour le chemin de dessin du widget RenderArea en définissant la propriété associée et en appelant la fonction QWidget::update(), ce qui force un rafraîchissement du widget selon les nouvelles préférences de rendu.
Le slot QWidget::update() ne provoque pas de rafraîchissement immédiat ; il planifie plutôt un événement de peinture qui sera traité lorsque Qt reviendra à la boucle d'événements principale.
void RenderArea::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);Un événement de dessin est une demande de rafraîchissement de tout ou partie du widget. La fonction `paintEvent()` est un gestionnaire d’événements qui peut être réimplémenté pour recevoir les événements de dessin du widget. Nous réimplémentons le gestionnaire d’événements pour rendre le chemin de dessin du widget ` RenderArea `.
Tout d’abord, nous créons un ` QPainter ` pour l’instance ` RenderArea `, puis nous définissons les indications de rendu du peintre. Les ` QPainter::RenderHints ` servent à spécifier des indicateurs à ` QPainter ` qui peuvent être respectés ou non par un moteur donné. ` QPainter::Antialiasing ` indique que le moteur doit, si possible, appliquer un anticrénelage aux bords des primitives, c’est-à-dire ajouter des pixels supplémentaires autour des pixels d’origine pour lisser les bords.
painter.scale(width() / 100.0, height() / 100.0);
painter.translate(50.0, 50.0);
painter.rotate(-rotationAngle);
painter.translate(-50.0, -50.0);Nous redimensionnons ensuite le système de coordonnées de l’ QPainter afin de garantir que le tracé de dessin soit affiché à la bonne taille, c’est-à-dire qu’il s’agrandisse avec le widget RenderArea lorsque l’application est redimensionnée. Lorsque nous avons construit les différents tracés de dessin, ils ont tous été rendus à l’intérieur d’un carré de 100 pixels de largeur, ce qui équivaut à RenderArea::sizeHint(). La fonction QPainter::scale() met à l’échelle le système de coordonnées en divisant la largeur et la hauteur actuelles du widget RenderArea par 100.
À présent, une fois que nous sommes sûrs que le tracé du peintre a la bonne taille, nous pouvons translater le système de coordonnées pour faire pivoter le tracé autour du centre du widget RenderArea. Après avoir effectué la rotation, nous devons penser à translater à nouveau le système de coordonnées dans le sens inverse.
painter.setPen(QPen(penColor, penWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
QLinearGradient gradient(0, 0, 0, 100);
gradient.setColorAt(0.0, fillColor1);
gradient.setColorAt(1.0, fillColor2);
painter.setBrush(gradient);
painter.drawPath(path);
}Ensuite, nous configurons le stylo de l’ QPainter avec les préférences de rendu de l’instance. Nous créons un QLinearGradient et définissons ses couleurs en fonction des couleurs de remplissage du widget RenderArea. Enfin, nous configurons le pinceau de l’ QPainter(le dégradé est automatiquement converti en QBrush), puis dessinons le chemin de dessin du widget RenderArea à l’aide de la fonction QPainter::drawPath().
© 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.