Sur cette page

Graphique de scène - Élément peint

Explique comment implémenter des éléments de graphe de scène personnalisés basés sur QPainter.

L'exemple « Élément peint » montre comment utiliser le framework de graphe de scène QML pour implémenter des éléments de graphe de scène personnalisés à l'aide d'QPainter.

Deux bulles de dialogue vertes, alignées à gauche et à droite, avec un bouton « Ajouter une autre bulle »

La classe ` QQuickPaintedItem ` est une classe dérivée de ` QQuickItem ` permettant d’implémenter des éléments personnalisés du graphe de scène QML à l’aide des interfaces ` QPainter `.

L’exemple se compose d’une classe d’élément et d’un fichier QML permettant d’utiliser cet élément. La classe ` TextBalloon ` représente les bulles de texte individuelles et étend la classe ` QQuickPaintedItem `, tandis que le fichier ` textballoons.qml ` sert à charger le module contenant le type QML `TextBalloon` et à afficher les bulles de texte.

Nous allons d’abord nous concentrer sur la classe TextBalloon, puis nous passerons au fichier textballoons.qml. Pour un exemple d’implémentation d’un plugin pour un module QML, veuillez consulter la section « Écrire un plugin d’extension ».

Déclaration de la classe TextBalloon

La classe ` TextBalloon ` hérite de ` QQuickPaintedItem`. ` QQuickPaintedItem ` est la classe de base de tous les éléments basés sur ` QPainter ` dans le framework QML Scene Graph.

class TextBalloon : public QQuickPaintedItem
{
    Q_OBJECT
    Q_PROPERTY(bool rightAligned READ isRightAligned WRITE setRightAligned NOTIFY rightAlignedChanged)
    QML_ELEMENT

    public:
        TextBalloon(QQuickItem *parent = nullptr);
        void paint(QPainter *painter) override;

        bool isRightAligned() const;
        void setRightAligned(bool rightAligned);

    private:
        bool rightAligned;

    signals:
        void rightAlignedChanged();
};

Pour implémenter un QQuickPaintedItem, vous devez implémenter la fonction virtuelle pure paint() de QQuickPaintedItem, qui gère le dessin du type.

Définition de la classe TextBalloon

Nous devons veiller à initialiser la propriété `rightAligned` pour un élément `TextBalloon`.

TextBalloon::TextBalloon(QQuickItem *parent)
    : QQuickPaintedItem(parent)
    , rightAligned(false)
{
}

Ensuite, nous implémentons la fonction ` paint() `, qui est automatiquement appelée par le framework Scene Graph pour dessiner le contenu de l’élément. Cette fonction dessine l’élément dans le système de coordonnées local.

void TextBalloon::paint(QPainter *painter)
{
    QBrush brush(QColor("#007430"));

    painter->setBrush(brush);
    painter->setPen(Qt::NoPen);
    painter->setRenderHint(QPainter::Antialiasing);

    QSizeF itemSize = size();
    painter->drawRoundedRect(0, 0, itemSize.width(), itemSize.height() - 10, 10, 10);

    if (rightAligned)
    {
        const QPointF points[3] = {
            QPointF(itemSize.width() - 10.0, itemSize.height() - 10.0),
            QPointF(itemSize.width() - 20.0, itemSize.height()),
            QPointF(itemSize.width() - 30.0, itemSize.height() - 10.0),
        };
        painter->drawConvexPolygon(points, 3);
    }
    else
    {
        const QPointF points[3] = {
            QPointF(10.0, itemSize.height() - 10.0),
            QPointF(20.0, itemSize.height()),
            QPointF(30.0, itemSize.height() - 10.0),
        };
        painter->drawConvexPolygon(points, 3);
    }
}

Nous commençons par définir le stylo et le pinceau de l’élément afin de déterminer son apparence. Ensuite, nous lançons le dessin. Notez que la fonction contentsBoundingRect() est appelée pour effectuer le dessin en fonction de la taille de l’élément. Le rectangle renvoyé par la fonction contentsBoundingRect() correspond à la taille de l’élément telle qu’elle est définie dans le fichier QML.

Fichier textballoons.qml

L’interface se compose de deux parties principales : la zone défilable contenant les bulles de texte et les boutons de commande permettant d’ajouter de nouvelles bulles.

BalloonView
ListModel {
    id: balloonModel
    ListElement {
        balloonWidth: 200
    }
    ListElement {
        balloonWidth: 120
    }
}

ListView {
    id: balloonView
    anchors.bottom: controls.top
    anchors.bottomMargin: 2
    anchors.top: parent.top
    delegate: TextBalloon {
        anchors.right: index % 2 !== 0 ? parent?.right : undefined
        height: 60
        rightAligned: index % 2 !== 0
        width: balloonWidth
    }
    model: balloonModel
    spacing: 5
    width: parent.width
}

Au démarrage de l’application, le `balloonModel` contient deux types qui seront affichés par le `balloonView`. Le `balloonView` alterne l’alignement des éléments délégués `TextBalloon` entre l’alignement à gauche et l’alignement à droite.

Commandes
Rectangle {
    id: controls

    anchors.bottom: parent.bottom
    anchors.left: parent.left
    anchors.margins: 1
    anchors.right: parent.right
    border.width: 2
    color: "white"
    height: parent.height * 0.15

    Text {
        anchors.centerIn: parent
        text: qsTr("Add another balloon")
    }

    MouseArea {
        anchors.fill: parent
        hoverEnabled: true
        onClicked: {
            balloonModel.append({"balloonWidth": Math.floor(Math.random() * 200 + 100)})
            balloonView.positionViewAtIndex(balloonView.count -1, ListView.End)
        }
        onEntered: {
            parent.color = "#8ac953"
        }
        onExited: {
            parent.color = "white"
        }
    }
}

La partie « contrôles » de l’interface utilisateur contient un rectangle doté d’un « MouseArea » qui change de couleur lorsque la souris passe dessus. Ce « bouton » de contrôle ajoute un nouvel objet à la fin du modèle, avec une largeur aléatoire.

Exemple de projet sur code.qt.io

© 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.