本页内容

场景图 - 绘制项

演示了如何基于QPainter 实现自定义场景图项。

“绘制项”示例演示了如何使用 QML 场景图框架,通过 `QPainter` 实现自定义场景图项。

两个绿色的对话气泡,分别对齐于左侧和右侧,旁边有一个“添加另一个气泡”按钮

QQuickPaintedItem 类是从QQuickItem 派生而来的类,用于通过QPainter 接口实现自定义QML场景图项。

该示例包含一个项类和一个用于使用该项的 QML 文件。TextBalloon 类通过继承QQuickPaintedItem 来表示单个文本气泡,而textballoons.qml 文件则用于加载包含 TextBalloon QML 类型的模块并显示文本气泡。

我们将首先重点介绍TextBalloon 类,随后再讲解textballoons.qml 文件。关于如何为QML模块实现插件的示例,请参阅《编写扩展插件》

TextBalloon 类声明

TextBalloon 类继承自QQuickPaintedItem 。QQuickPaintedItem 是QML场景图框架中所有基于QPainter 项的基类。

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

要实现QQuickPaintedItem ,必须实现QQuickPaintedItem的纯虚函数paint(),该函数负责实现该类型的绘制。

TextBalloon 类定义

我们必须确保为 TextBalloon 项初始化 rightAligned 属性。

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

然后,我们实现paint() 函数,该函数会由场景图框架自动调用以绘制项的内容。该函数在本地坐标系中绘制该项。

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

首先,我们设置项的笔和画笔参数以定义项的外观。之后开始绘制。请注意,contentsBoundingRect() 函数的调用取决于项的大小。contentsBoundingRect() 函数返回的矩形即为 QML 文件中定义的项的大小。

textballoons.qml 文件

该界面由两个主要部分组成:包含对话气泡的可滚动区域,以及用于添加新气泡的控制按钮。

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
}

在应用程序启动时,balloonModel 包含两种类型的气泡,这些气泡将由 balloonView 显示。balloonView 会交替显示左对齐和右对齐的 TextBalloon 委托项。

控件
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"
        }
    }
}

UI 的控件部分包含一个矩形,其中嵌有MouseArea 控件,当鼠标悬停在其上方时,该控件会改变颜色。该“按钮”控件会以随机宽度将一个新对象添加到模型的末尾。

示例项目 @ 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.