Sur cette page

Graphique de scène - Élément peint

Montre comment mettre en œuvre des éléments de graphe de scène personnalisés basés sur QPainter.

L'exemple de l'élément peint montre comment utiliser le cadre QML Scene Graph pour mettre en œuvre des éléments de graphe de scène personnalisés à l'aide de QPainter.

La classe QQuickPaintedItem est une classe dérivée de QQuickItem qui permet de mettre en œuvre des éléments QML Scene Graph personnalisés à l'aide des interfaces QPainter.

L'exemple se compose d'une classe d'élément et d'un fichier QML permettant d'utiliser l'élément. La classe TextBalloon représente les ballons de texte individuels en étendant QQuickPaintedItem et le fichier textballoons.qml est utilisé pour charger le module contenant le type QML TextBalloon et afficher les ballons de texte.

Nous nous concentrerons d'abord sur la classe TextBalloon, puis sur le fichier textballoons.qml. Pour un exemple de mise en œuvre d'un plugin pour un module QML, veuillez consulter le document Writing an Extension Plugin (écrire un plugin d'extension).

Déclaration de la classe TextBalloon

La classe TextBalloon hérite de QQuickPaintedItem. QQuickPaintedItem est la classe de base pour tous les éléments basés sur QPainter dans le cadre 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 QQuickPaintedIem, qui implémente la peinture du type.

Définition de la classe TextBalloon

Nous devons nous assurer d'initialiser la propriété rightAligned pour un élément TextBalloon.

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

Nous implémentons ensuite la fonction paint() qui est automatiquement appelée par le Scene Graph framework pour peindre le contenu de l'élément. La fonction peint l'élément en coordonnées locales.

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 placer le stylo et le pinceau sur l'élément pour en définir l'aspect. Ensuite, nous commençons à dessiner. Notez que l'élément contentsBoundingRect() est appelé pour dessiner 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 de défilement avec les ballons de texte et le bouton de contrôle permettant d'ajouter de nouveaux ballons.

Vue du ballon
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
}

Le balloonModel contient deux types au début de l'application qui seront affichés par le balloonView. Le balloonView alterne les éléments du délégué TextBalloon entre aligné à gauche et aligné à droite.

Contrôles
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 avec une adresse MouseArea qui change de couleur lorsque la souris le survole. Ce contrôle "bouton" ajoute un nouvel objet à la fin du modèle avec une largeur aléatoire.

Exemple de projet @ 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.