Qt 画布画家 - Hello Widgets 示例

演示了QCanvasPainterQCanvasPainterWidget 的使用。

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

QCanvasPainterWidget QRhiWidget 源自 ,并始终通过 使用加速 3D 渲染。QRhi

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, 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,QCanvasImageQFont

图像被用作填充心形的图案:

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

当涉及QCanvasImageQCanvasOffscreenCanvas 等资源时,这些资源由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() 中为所有QCanvasImageQCanvasOffscreenCanvas 变量分配一个默认的空对象也是一种不错的模式。

main() 函数创建了QMainWindowQMdiArea 。可以添加多个 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.