Szenengraph - Gemaltes Element

Zeigt, wie man QPainter-basierte benutzerdefinierte Scenegraph-Elemente implementiert.

Das Painted Item Beispiel zeigt, wie man das QML Scene Graph Framework verwendet, um benutzerdefinierte Scenegraph Items mit QPainter zu implementieren.

Die Klasse QQuickPaintedItem ist eine von QQuickItem abgeleitete Klasse zur Implementierung benutzerdefinierter QML Scene Graph-Elemente unter Verwendung der Schnittstellen QPainter.

Das Beispiel besteht aus einer Item-Klasse und einer QML-Datei zur Verwendung des Items. Die Klasse TextBalloon stellt die einzelnen Textballons dar, die QQuickPaintedItem erweitern, und die Datei textballoons.qml wird verwendet, um das Modul zu laden, das den QML-Typ TextBalloon enthält, und um die Textballons anzuzeigen.

Wir werden uns zunächst auf die Klasse TextBalloon konzentrieren und dann mit der Datei textballoons.qml fortfahren. Ein Beispiel für die Implementierung eines Plugins für ein QML-Modul finden Sie unter Writing an Extension Plugin

TextBalloon Klassendeklaration

Die Klasse TextBalloon erbt von QQuickPaintedItem. QQuickPaintedItem ist die Basisklasse für alle QPainter basierten Elemente im QML Scene Graph Framework.

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();
};

Um ein QQuickPaintedItem zu implementieren, müssen Sie die rein virtuelle Funktion paint() von QQuickPaintedIem implementieren, die das Malen des Typs implementiert.

TextBalloon Klassendefinition

Wir müssen sicherstellen, dass die Eigenschaft rightAligned für ein TextBalloon-Element initialisiert wird.

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

Dann implementieren wir die Funktion paint(), die automatisch vom Scene Graph Framework aufgerufen wird, um den Inhalt des Elements zu zeichnen. Die Funktion malt das Element in lokalen Koordinaten.

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);
    }
}

Wir beginnen mit der Einstellung von Stift und Pinsel auf dem Element, um das Aussehen des Elements zu definieren. Danach beginnen wir mit dem Zeichnen. Beachten Sie, dass die Funktion contentsBoundingRect() aufgerufen wird, um abhängig von der Größe des Elements zu zeichnen. Das Rechteck, das von der Funktion contentsBoundingRect() zurückgegeben wird, entspricht der Größe des Elements, wie sie in der QML-Datei definiert ist.

textballoons.qml Datei

Die Schnittstelle besteht aus zwei Hauptteilen. Dem scrollbaren Bereich mit den Textballons und der Schaltfläche zum Hinzufügen neuer Ballons.

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
}

Das balloonModel enthält beim Start der Anwendung zwei Typen, die von der balloonView angezeigt werden. Die BalloonView wechselt die TextBalloon Delegate Items zwischen links- und rechtsbündig.

Steuerelemente
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"
        }
    }
}

Der Controls-Teil der UI enthält ein Rechteck mit einem MouseArea, das seine Farbe ändert, wenn die Maus darüber fährt. Dieses Steuerelement "Button" fügt ein neues Objekt am Ende des Modells mit einer zufälligen Breite hinzu.

Beispielprojekt @ code.qt.io

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