Qt 캔버스 페인터 - 갤러리 예제
Qt Quick 애플리케이션에서 QCanvasPainter 기능을 시연합니다.

갤러리 예제는 Qt Quick 애플리케이션으로 QCanvasPainter 에서 제공하는 다양한 기능을 보여줍니다.
사용자 인터페이스는 기본적으로 ListView 이며, 델리게이트는 C++ 로 구현되고 QML에 노출된 유형인 GalleryItem 입니다.
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와 캔버스 페인터에서는 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 synchronize(QCanvasPainterItem *item) override; void paint(QCanvasPainter *painter) override;
초기화자원()은 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")); 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.setTimeRunning(true); m_customBrush2.setTimeRunning(true); m_customBrush3.setTimeRunning(true); m_customBrush4.setTimeRunning(true); }
synchronize()는 나중에 Qt Quick 장면 그래프의 렌더 스레드에서 안전하게 액세스할 수 있도록 GalleryItem 데이터를 복사하는 작업을 처리합니다:
void GalleryItemRenderer::synchronize(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; } } }
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_viewSaturate = m_animState; painter->setGlobalAlpha(m_viewAlpha); painter->setGlobalSaturate(m_viewSaturate); 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() / (rects+2) - margin; float w2 = w - border; float posX = w + 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;
자세한 내용은 아래에 링크된 전체 예제 소스 코드를 확인하세요.
© 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.