Qt Canvas Painter - ギャラリーの例

Qt Quick アプリケーションにおいて、QCanvasPainter の機能を実演します。

「グラデーションと画像パターン」と題されたブラシギャラリー。グラデーションの見本とパターン化されたタイルがグリッド状に並んでいる。

ギャラリーのサンプルは、Qt Quick アプリケーションであり、QCanvasPainter が提供する幅広い機能を紹介しています。

ユーザーインターフェースは本質的にListView であり、そのデリゲートはGalleryItem です。これはC++で実装され、QMLから利用可能な型です。

class GalleryItem : public QCanvasPainterItem
{
    Q_OBJECT
    QML_NAMED_ELEMENT(GalleryItem)
    Q_PROPERTY(int galleryView READ galleryView WRITE setGalleryView NOTIFY galleryViewChanged)
    Q_PROPERTY(float animationTime READ animationTime WRITE setAnimationTime NOTIFY animationTimeChanged)
    Q_PROPERTY(float animationSine READ animationSine WRITE setAnimationSine NOTIFY animationSineChanged)
    Q_PROPERTY(float animState READ animState WRITE setAnimState NOTIFY animStateChanged)

Qt 5 および OpenGL を使用していた場合、GalleryItem はQQuickPaintedItem のサブクラスにできたでしょう。Qt 6 および Canvas Painter では、QQuickPaintedItem やQPainter による通常のソフトウェアレンダリングを使用する代わりに、QCanvasPainter を通じて高速化されたレンダリングを提供するQCanvasPainterItem をサブクラス化します。

GalleryItemの実装は単純です。仮想関数createItemRenderer()を再実装し、QCanvasPainterItemRenderer をサブクラス化したGalleryItemRendererのインスタンスを作成します。

GalleryItem::GalleryItem(QQuickItem *parent)
:  QCanvasPainterItem(parent)
{
}

QCanvasPainterItemRenderer* GalleryItem::createItemRenderer() const
{
    return new GalleryItemRenderer();
}

実際の描画処理はこのクラスで実装されています:

class GalleryItemRenderer : public QCanvasPainterItemRenderer
{
public:
    explicit GalleryItemRenderer();
    ~GalleryItemRenderer();

    void initializeResources(QCanvasPainter *painter) override;
    void synchronizeData(QCanvasPainterItem *item) override;
    void paint(QCanvasPainter *painter) override;

initializeResources() では、QImage を通じて読み込まれた画像や、カスタムブラシ用のシェーダーを登録します。

void GalleryItemRenderer::initializeResources(QCanvasPainter *painter)
{
    QCanvasPainter::ImageFlags flags = QCanvasPainter::ImageFlag::Repeat | QCanvasPainter::ImageFlag::GenerateMipmaps;
    m_patternImage = painter->addImage(QImage(":/images/pattern1.png"), flags);
    m_patternImage2 = painter->addImage(QImage(":/images/pattern2.png"), flags);
    m_patternImage3 = painter->addImage(QImage(":/images/pattern3.png"), flags);
    m_testImage = painter->addImage(QImage(":/images/qt_development_white.png"));
    m_gradientImage1 = painter->addImage(QImage(":/images/gradient1.png"));
    m_gradientImage2 = painter->addImage(QImage(":/images/gradient2.png"));
    m_gradientImage3 = painter->addImage(QImage(":/images/gradient3.png"));
    image3Gray = painter->addImage(QImage(":/images/face-smile-bw.png"));
    image3Plain = painter->addImage(QImage(":/images/pattern2.png"));
    image3Nearest = painter->addImage(QImage(":/images/pattern2.png"),
                                        QCanvasPainter::ImageFlag::Nearest);
    image3Mips = painter->addImage(QImage(":/images/pattern2.png"),
                                     QCanvasPainter::ImageFlag::GenerateMipmaps);
    image3NearestMips = painter->addImage(QImage(":/images/pattern2.png"),
                                            QCanvasPainter::ImageFlag::Nearest | QCanvasPainter::ImageFlag::GenerateMipmaps);
    m_customBrush.setFragmentShader(":/qcgalleryexample/brush1.frag.qsb");
    m_customBrush2.setFragmentShader(":/qcgalleryexample/brush2.frag.qsb");
    m_customBrush3.setFragmentShader(":/qcgalleryexample/brush3.frag.qsb");
    m_customBrush3.setVertexShader(":/qcgalleryexample/brush3.vert.qsb");
    m_customBrush4.setFragmentShader(":/qcgalleryexample/brush4.frag.qsb");
    // Enable iTime animations
    m_customBrush.setAnimationRunning(true);
    m_customBrush2.setAnimationRunning(true);
    m_customBrush3.setAnimationRunning(true);
    m_customBrush4.setAnimationRunning(true);
}

synchronizeData() は、後でQt Quick のシーングラフのレンダリングスレッドから安全にアクセスできるよう、GalleryItem データのコピー処理を行います:

void GalleryItemRenderer::synchronizeData(QCanvasPainterItem *item)
{
    // Setting values here synchronized
    GalleryItem *realItem = static_cast<GalleryItem*>(item);
    if (realItem) {
        m_animationTime = realItem->animationTime();
        m_animationSine = realItem->animationSine();
        m_animState = realItem->animState();
        m_viewIndex = realItem->galleryView();
        if (!qFuzzyCompare(m_previousWidth, width()) ||
            !qFuzzyCompare(m_previousHeight, height())) {
            m_sizeChanged = true;
            m_previousWidth = width();
            m_previousHeight = height();
        } else {
            m_sizeChanged = false;
        }
        loadTigerPath();
    }

}

paint() の実装では、ListView から提供される現在のインデックスに基づいて、QCanvasPainter を使用してレンダリングを行います:

void GalleryItemRenderer::paint(QCanvasPainter *painter)
{
    Q_UNUSED(painter)

    // Views not currently centered to have reduced
    // alpha and saturation.
    m_viewAlpha = 0.2 + 0.8 * m_animState;
    m_viewSaturation = m_animState;
    painter->setGlobalAlpha(m_viewAlpha);
    painter->setGlobalSaturation(m_viewSaturation);
    m_topMargin = height() * 0.02f;
    switch (m_viewIndex) {
    case 0:
        drawRectsWithLinearGradient();
        drawRectsWithRadialGradient();
        drawRectsWithBoxGradient();
        drawRectsWithConicalGradients();
        drawRectsWithImagePattern();
        drawRectsWithBrushStroke();
        break;
    case 1:
        drawImages();
        break;
    case 2:
        drawGridPatterns();
        break;

ここから呼び出される関数は、QCanvasPainter API を使用してレンダリングを実行します。例えば:

void GalleryItemRenderer::drawRectsWithBrushStroke()
{
    int rects = 3;
    float margin = width()*0.02f;
    float border = margin + margin * m_animationSine;
    float w = (width() - margin) / (rects+2) - margin;
    float w2 = w - border;
    float posX = w + 2 * margin + border/2;
    float posY = m_topMargin + 5*(w+margin) + border/2;

    QRectF rect1(posX,posY,w2,w2);
    painter()->setLineWidth(border);
    painter()->setFillStyle(QCanvasImagePattern(m_patternImage3));
    QCanvasLinearGradient g1(posX, posY, posX+w2, posY+w2);
    g1.setStartColor("#ffffff");
    g1.setEndColor("#000000");
    painter()->setStrokeStyle(g1);
    painter()->beginPath();
    painter()->roundRect(rect1, border);
    painter()->fill();
    painter()->stroke();
    posX += w + margin;

詳細については、以下にリンクされた完全なサンプルソースコードをご確認ください。

サンプルプロジェクト @ 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.