Exemple de chemins de peinture
L'exemple des chemins de peinture montre comment utiliser les chemins de peinture pour construire des formes complexes pour le rendu.

La classe QPainterPath fournit un conteneur pour les opérations de peinture, ce qui permet de construire et de réutiliser des formes graphiques.
Un chemin de peinture est un objet composé d'un certain nombre de blocs de construction graphiques (tels que des rectangles, des ellipses, des lignes et des courbes), et peut être utilisé pour le remplissage, le contour et l'écrêtage. Le principal avantage des chemins de peintre par rapport aux opérations de dessin normales est que les formes complexes ne doivent être créées qu'une seule fois, mais qu'elles peuvent être dessinées plusieurs fois en utilisant uniquement des appels à QPainter::drawPath().
L'exemple se compose de deux classes :
- La classe
RenderAreaqui est un widget personnalisé affichant un seul chemin de peinture. - La classe
Windowest la fenêtre principale de l'application qui affiche plusieurs widgetsRenderAreaet permet à l'utilisateur de manipuler le remplissage, le stylo, la couleur et l'angle de rotation des chemins de peinture.
Nous examinerons d'abord la classe Window, puis la classe RenderArea.
Définition de la classe Window
La classe Window hérite de QWidget et constitue la fenêtre principale de l'application. Elle affiche plusieurs widgets RenderArea et permet à l'utilisateur de manipuler 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 emplacements privés pour répondre aux entrées 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 tant qu'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 quelques fonctions de commodité privées : populateWithColors() remplit un QComboBox donné avec des éléments correspondant aux noms de couleur que Qt connaît, et currentItemData() renvoie l'élément actuel pour un QComboBox donné.
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; };
Nous déclarons ensuite 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.
Mise en œuvre de la classe de fenêtre
Dans le constructeur Window, nous définissons les différents chemins de peinture et créons les widgets RenderArea correspondants qui rendront 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 peintre est un objet composé d'un certain nombre de blocs de construction graphiques, c'est-à-dire de sous-chemins. Le déplacement du point courant démarrera également un nouveau sous-chemin (fermant implicitement le chemin courant précédent lorsque le nouveau est démarré). La fonction QPainterPath::lineTo() ajoute une ligne droite entre le point courant et le point final donné. Une fois la ligne tracée, le point courant est mis à jour pour se situer à l'extrémité de la ligne.
Nous déplaçons d'abord le point courant à partir d'un nouveau sous-chemin et nous dessinons trois des côtés du rectangle. Nous appelons ensuite la fonction QPainterPath::closeSubpath() qui trace une ligne jusqu'au début du sous-chemin actuel. Un nouveau sous-chemin est automatiquement créé lorsque le sous-chemin actuel est fermé. Le point actuel du nouveau chemin est (0, 0). Nous aurions également pu appeler QPainterPath::lineTo() pour dessiner la dernière ligne, puis démarrer explicitement un nouveau sous-chemin à l'aide de la fonction QPainterPath::moveTo().
QPainterPath fournit également la fonction de commodité QPainterPath::addRect(), qui ajoute un rectangle donné au chemin en tant que sous-chemin 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 chemin du peintre après l'ajout du rectangle est le coin supérieur gauche du rectangle.
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 dessiner 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 QRect ou les coordonnées du rectangle), commençant à l'angle de départ donné et s'étendant aux degrés donnés dans le sens inverse des aiguilles d'une montre. Les angles sont spécifiés en degrés. Les arcs dans le sens des aiguilles d'une montre peuvent être spécifiés en utilisant des angles négatifs. La fonction relie le point actuel 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 la trajectoire de l'ellipse. Tout d'abord, nous déplaçons le point actuel en commençant par une nouvelle trajectoire. Ensuite, nous appelons QPainterPath::arcTo() avec un angle de départ de 0,0 et 360,0 degrés comme dernier argument, créant ainsi une ellipse.
Là encore, QPainterPath fournit une fonction de commodité ( QPainterPath::addEllipse()) qui crée une ellipse à l'intérieur d'un rectangle de délimitation donné et l'ajoute au chemin du peintre. Si le sous-chemin actuel est fermé, un nouveau sous-chemin est lancé. L'ellipse est composée d'une courbe dans le sens des aiguilles d'une montre, commençant et finissant à zéro degré (la 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 chemin du diagramme circulaire, nous continuons à utiliser une combinaison des fonctions mentionnées : Tout d'abord, nous déplaçons le point actuel, en commençant un nouveau sous-chemin. Ensuite, nous créons une ligne entre le centre du graphique et l'arc, ainsi que l'arc lui-même. Lorsque nous fermons le sous-chemin, nous construisons implicitement la dernière ligne jusqu'au centre du graphique.
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 est équivalente à la construction d'un rectangle.
QPainterPath fournit également la fonction de commodité QPainterPath::addPolygon() qui ajoute le polygone donné au chemin en tant que nouveau sous-chemin. La position actuelle après l'ajout du polygone est le dernier point du polygone.
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 chemin composé d'un groupe de sous-chemins : Tout d'abord, nous déplaçons le point courant et 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 lorsque nous avons créé le chemin de l'ellipse. Ensuite, nous déplaçons à nouveau le point courant, en commençant un nouveau chemin secondaire, et nous construisons trois côtés d'un carré à l'aide de la fonction QPainterPath::lineTo().
Maintenant, 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-chemin actuel, c'est-à-dire le carré.
QPainterPath fournissent 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 chemin de texte, nous créons d'abord la police de caractères. 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. QFont::ForceOutline force l'utilisation de polices de contour.
Pour construire le texte, nous utilisons la fonction QPainterPath::addText() qui ajoute le texte donné au chemin sous la forme d'un ensemble de sous-chemins fermés créés à partir de la police fournie. Les sous-chemins 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 chemin de Bézier, nous utilisons la fonction QPainterPath::cubicTo() qui ajoute une courbe de Bézier entre le point actuel et le point final donné avec le point de contrôle donné. Après l'ajout de la courbe, le point courant est mis à jour pour se trouver au point final de la courbe.
Dans ce cas, nous omettons de fermer le sous-chemin, de sorte que nous n'avons qu'une simple courbe. Mais il existe toujours une ligne logique entre le point final de la courbe et le début du sous-chemin ; elle devient visible lors du remplissage du chemin, 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 chemin final que nous avons construit montre que vous pouvez utiliser QPainterPath pour construire 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 peinture dont nous avons besoin, nous créons un widget RenderArea correspondant à 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 peinture.
Il existe deux règles de remplissage 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 à partir du point jusqu'à un endroit situé à l'extérieur de la forme, et compte le nombre d'intersections. Si le nombre d'intersections est impair, le point est à l'intérieur de la forme. Cette règle est 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 à partir du point jusqu'à un endroit situé à l'extérieur de la forme. Elle détermine ensuite si la direction de la ligne à chaque point d'intersection est ascendante ou descendante. Le nombre d'enroulements 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 des comboboxes activated() aux emplacements associés dans la classe Window, tandis que nous connectons les signaux des spin boxes valueChanged() directement aux emplacements 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 disposition séparée que nous ajoutons ensuite à la disposition 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 emplacements fillRuleChanged(), fillGradientChanged() et penColorChanged(), et 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 mis en œuvre pour récupérer la ou les nouvelles valeurs des comboboxes associées et mettre à jour les widgets RenderArea.
Nous commençons par déterminer 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 pour mettre à jour les chemins du peintre.
void Window::populateWithColors(QComboBox *comboBox) { const QStringList colorNames = QColor::colorNames(); for (const QString &name : colorNames) comboBox->addItem(name, QColor(name)); }
La fonction populateWithColors() remplit le combobox donné avec des éléments correspondant aux noms de couleurs que Qt connaît et qui sont 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 boîte combobox donnée.
Définition de la classe RenderArea
La classe RenderArea hérite de QWidget, et est un widget personnalisé affichant un seul chemin de peinture.
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 emplacements publics mettant à jour le chemin de peinture associé au widget RenderArea. En outre, nous réimplémentons les fonctions QWidget::minimumSizeHint() et QWidget::sizeHint() pour donner au widget RenderArea une taille raisonnable dans notre application, et nous réimplémentons le gestionnaire d'événement QWidget::paintEvent() pour dessiner son chemin de peintre.
private: QPainterPath path; QColor fillColor1; QColor fillColor2; int penWidth; QColor penColor; int rotationAngle; };
Chaque instance de la classe RenderArea possède un QPainterPath, quelques couleurs de remplissage, une largeur de stylo, une couleur de stylo et un angle de rotation.
Mise en œuvre de la classe RenderArea
Le constructeur prend un QPainterPath comme 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 ainsi que la largeur du stylo et l'angle de rotation. Nous définissons également le widget background role; QPalette::Base est généralement blanc.
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() pour donner au widget RenderArea une taille raisonnable dans 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 du peintre du widget RenderArea en définissant la propriété associée et appellent la fonction QWidget::update(), ce qui oblige à repeindre le widget avec les nouvelles préférences de rendu.
Le slot QWidget::update() ne provoque pas un repeint immédiat ; au lieu de cela, il planifie un événement de peinture à traiter lorsque Qt revient à la boucle d'événements principale.
void RenderArea::paintEvent(QPaintEvent *) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing);
Un événement de peinture est une demande de repeindre 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 peinture du widget. Nous réimplémentons le gestionnaire d'événements pour rendre le chemin de peinture du widget RenderArea.
Tout d'abord, nous créons un QPainter pour l'instance RenderArea et définissons les indices de rendu du peintre. Les QPainter::RenderHints sont utilisés pour spécifier des drapeaux à QPainter qui peuvent, ou non, être respectés par un moteur donné. QPainter::Antialiasing indique que le moteur doit antialiaser les bords des primitives si possible, c'est-à-dire mettre 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);
Ensuite, nous mettons à l'échelle le système de coordonnées de QPainter pour nous assurer que le chemin du peintre est rendu à la bonne taille, c'est-à-dire qu'il grandit avec le widget RenderArea lorsque l'application est redimensionnée. Lorsque nous avons construit les différents chemins de peinture, ils ont tous été rendus à l'intérieur d'un carré d'une largeur de 100 pixels, ce qui équivaut à RenderArea::sizeHint(). La fonction QPainter::scale() met à l'échelle le système de coordonnées en fonction de la largeur et de la hauteur actuelles du widget RenderArea, divisées par 100.
Maintenant, lorsque nous sommes sûrs que le chemin de peinture a la bonne taille, nous pouvons traduire le système de coordonnées pour faire tourner le chemin de peinture autour du centre du widget RenderArea. Après avoir effectué la rotation, nous devons nous rappeler de translater à nouveau le système de coordonnées.
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 définissons la plume de 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 définissons le pinceau de QPainter(le gradient est automatiquement converti en QBrush), et nous dessinons le chemin du peintre 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.