Qt Canvas Painter - “Hello” 控件示例

演示了如何使用QCanvasPainter 和QCanvasPainterWidget 。

主窗口中包含一个子控件,该控件显示“Hello Qt Canvas Painter”字样,并在径向渐变背景上绘制了一个带有图案的绿色心形

该示例实现了一个QCanvasPainterWidget 的子类。随后,可以将该控件的一个或多个实例添加到QMainWindow 中的QMdiArea 内。

QCanvasPainterWidget 该组件本身继承自QRhiWidget ,并始终通过QRhi 使用加速的3D渲染。

QCanvasPainterWidget 的子类至少需要实现paint() 方法。本示例还使用了一张从 PNG 文件加载的图像。

class CanvasWidget : public QCanvasPainterWidget
{
public:
    CanvasWidget();
    void initializeResources(QCanvasPainter *p) override;
    void paint(QCanvasPainter *p) override;
    void graphicsResourcesInvalidated() override;

private:
    QCanvasImage m_image;
};

paint() 函数可以立即使用提供者QCanvasPainter 开始绘制:

void CanvasWidget::paint(QCanvasPainter *p)
{
    const float size = std::min(width(), height());
    const float centerX = width() / 2;
    const float centerY = height() / 2;

    // Paint the background circle
    QCanvasRadialGradient gradient1(centerX, centerY - size * 0.1f, 0, size * 0.6f);
    gradient1.setStartColor(QColor(0x909090));
    gradient1.setEndColor(QColor(0x404040));
    p->beginPath();
    p->circle(QPointF(centerX, centerY), size * 0.46f);
    p->setFillStyle(gradient1);
    p->fill();
    p->setStrokeStyle(QColor(0x202020));
    p->setLineWidth(size * 0.02f);
    p->stroke();

有关本示例所用功能的更多信息,请参阅QCanvasPainter 、QCanvasBrush 、QCanvasRadialGradient 、QCanvasImagePattern 、QCanvasImage 以及QFont 。

该图像用作图案,用于填充心形:

    // Paint heart
    QCanvasImagePattern pattern(m_image, centerX, centerY, size * 0.08f, size * 0.05f);
    p->setFillStyle(pattern);

当涉及QCanvasImage 和QCanvasOffscreenCanvas 等资源时,这些资源在initializeResources() 和graphicsResourcesInvalidated() 中进行管理:

void CanvasWidget::initializeResources(QCanvasPainter *p)
{
    Q_ASSERT(m_image.isNull());
    const auto flags = QCanvasPainter::ImageFlag::Repeat | QCanvasPainter::ImageFlag::GenerateMipmaps;
    m_image = p->addImage(QImage(u":/qt-translucent.png"_s), flags);
}

void CanvasWidget::graphicsResourcesInvalidated()
{
    m_image = {};
}

initializeResources() 仅作为一种便捷方式。与其实现该方法,也可以在 paint() 中编写以下代码:

if (m_image.isNull())
    m_image = p->addImage(QImage(":/qt-translucent.png"), QCanvasPainter::ImageFlag::Repeat);

此示例不会在窗口之间重新关联小部件,因此图形资源不会丢失。尽管如此,在 graphicsResourcesInvalidated() 中将默认的空对象赋值给所有QCanvasImage 和QCanvasOffscreenCanvas 变量仍是一个良好的编程模式。

main() 函数会创建一个QMainWindow 和一个QMdiArea 。可以将多个 CanvasWidget 类的实例作为子窗口添加。由于hasSharedPainter() 的默认值为 true,且这些窗口位于同一个顶级小部件内,因此所有绘图小部件将共享同一个QCanvasPainter 及其相关的渲染基础设施,而非各自创建独立的实例。

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