Qt Canvas Painter - コンパクトヘルスの例
QWindow におけるQCanvasPainter の使用例を示します。

この例では、純粋なQWindow アプリケーションで Qt Canvas Painter を使用しています。Qt Quick やQWidget はまったく使用されておらず、Core、GUI、Canvas Painter 以外の Qt モジュールへの依存はありません。
このアプリケーションでは、QRhi を使用してアクセラレーテッド 3D レンダリングを設定し、QCanvasPainter を使用してウィンドウ内のすべてのコンテンツをレンダリングします。レンダリングとQCanvasPainter のQRhi との統合は、QCanvasRhiPaintDriver を介して管理されます。
ウォークスルー
プラットフォームに基づいて使用する3D APIを選択する一方で、アプリケーションはコマンドライン引数を使用したリクエストの可能性も提供します。
int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); app.setAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents); QRhi::Implementation graphicsApi; #if defined(Q_OS_WIN) graphicsApi = QRhi::D3D11; #elif QT_CONFIG(metal) graphicsApi = QRhi::Metal; #elif QT_CONFIG(vulkan) graphicsApi = QRhi::Vulkan; #else graphicsApi = QRhi::OpenGLES2; #endif QCommandLineParser cmdLineParser; cmdLineParser.addHelpOption(); QCommandLineOption nullOption({ "n", "null" }, QLatin1String("Null")); cmdLineParser.addOption(nullOption); QCommandLineOption glOption({ "g", "opengl" }, QLatin1String("OpenGL")); cmdLineParser.addOption(glOption); QCommandLineOption vkOption({ "v", "vulkan" }, QLatin1String("Vulkan")); cmdLineParser.addOption(vkOption); QCommandLineOption d3d11Option({ "d", "d3d11" }, QLatin1String("Direct3D 11")); cmdLineParser.addOption(d3d11Option); QCommandLineOption d3d12Option({ "D", "d3d12" }, QLatin1String("Direct3D 12")); cmdLineParser.addOption(d3d12Option); QCommandLineOption mtlOption({ "m", "metal" }, QLatin1String("Metal")); cmdLineParser.addOption(mtlOption); cmdLineParser.process(app); if (cmdLineParser.isSet(nullOption)) graphicsApi = QRhi::Null; if (cmdLineParser.isSet(glOption)) graphicsApi = QRhi::OpenGLES2; if (cmdLineParser.isSet(vkOption)) graphicsApi = QRhi::Vulkan; if (cmdLineParser.isSet(d3d11Option)) graphicsApi = QRhi::D3D11; if (cmdLineParser.isSet(d3d12Option)) graphicsApi = QRhi::D3D12; if (cmdLineParser.isSet(mtlOption)) graphicsApi = QRhi::Metal; #if QT_CONFIG(opengl) QSurfaceFormat fmt; fmt.setDepthBufferSize(24); fmt.setStencilBufferSize(8); #ifdef Q_OS_MACOS fmt.setVersion(4, 1); fmt.setProfile(QSurfaceFormat::CoreProfile); #endif QSurfaceFormat::setDefaultFormat(fmt); #endif MainWindow window(graphicsApi); window.resize(1920 / 2, 1080 / 2); window.show(); return app.exec(); }
MainWindow は PainterWindow のサブクラスで、QWindow です。PainterWindow は Qt の 3D グラフィックス抽象であるQRhi を介してレンダリングされたコンテンツを表示するウィンドウを実装しています。そのタスクは、expose イベントを受信したとき、つまりウィンドウが表示されたときにQRhi インスタンスを初期化すること、スワップチェーンとデプス ステンシル バッファを管理すること、ウィンドウのサイズが変更されたときの処理を行うこと、そして MainWindow に実装されている仮想 paint() 関数を呼び出すことです。
PainterWindow の実装をよりよく理解するには、RHI Window Example をチェックすることをお勧めします。
QCanvasPainter 特有の手順としては、QRhi が正常に初期化されたら、QCanvasPainterFactory インスタンスを取得することです:
if (!m_factory) { m_factory = new QCanvasPainterFactory; m_factory->create(m_rhi.get()); }
新しいフレームのレンダリングは render() 関数で行われます。この関数は、ウィンドウが表示されるとき、サイズが変更されるとき、およびrequestUpdate() 経由でスケジュールされた更新要求に応答するときに呼び出されます。
RHIウィンドウの例とは異なり、QRhi APIを介して頂点およびユニフォームバッファまたはグラフィックスパイプラインを作成し、直接描画コールを発行することはありません。代わりに、QCanvasPainter-生成されたレンダリングでレンダーパスを記録するために、QCanvasRhiPaintDriver が使用されます。
voidPainterWindow::render() {if(!m_factory|| !m_factory->isValid()|| !m_rhi|| !m_sc)return;if(!m_hasSwapChain||m_notExposed)return;if(m_sc->currentPixelSize() != m_sc->surfacePixelSize()||m_newlyExposed) { resizeSwapChain();if(!m_hasSwapChain)return; m_newlyExposed= false; }. QRhi::FrameOpResult r= m_rhi->beginFrame(m_sc.get());if(r==) QRhi::FrameOpSwapChainOutOfDate) { resizeSwapChain();if(!m_hasSwapChain)return; r= m_rhi->beginFrame(m_sc.get()); }if(r!=) QRhi::FrameOpSuccess){。 qDebug("beginFrame failed with %d, retry", r); requestUpdate();return; }. QRhiCommandBuffer*cb = m_sc->currentFrameCommandBuffer(); QRhiRenderTarget*rt = m_sc->currentFrameRenderTarget(); QCanvasRhiPaintDriver*pd = m_factory->paintDriver(); QCanvasPainter*pd->resetForNewFrame(); pd->beginPaint(cb,rt,m_fillColor,size(), float(devicePixelRatio())); paint(painter); pd->endPaint(); m_rhi->endFrame(m_sc.get()); }
MainWindowのpaint()実装は、QCanvasPainter APIで動作し、QRhi のような低レベルの詳細を気にする必要はありません。
まず、画像の読み込みと登録を行います:
void MainWindow::paint(QCanvasPainter *p) { if (!m_initialized) { auto flags = QCanvasPainter::ImageFlag::GenerateMipmaps; m_b1ImageLight = p->addImage(QImage(":/images/icon_random_light.png"), flags); m_b1ImageDark = p->addImage(QImage(":/images/icon_random_dark.png"), flags); m_b2ImageLight = p->addImage(QImage(":/images/icon_theme_light.png"), flags); m_b2ImageDark = p->addImage(QImage(":/images/icon_theme_dark.png"), flags); m_b3ImageLight = p->addImage(QImage(":/images/icon_settings_light.png"), flags); m_b3ImageDark = p->addImage(QImage(":/images/icon_settings_dark.png"), flags); m_sImageLight = p->addImage(QImage(":/images/icon_run_light.png"), flags); m_sImageDark = p->addImage(QImage(":/images/icon_run_dark.png"), flags); m_initialized = true; }
続いて、パスの塗りつぶしや描画、テキストのレンダリング、画像の描画などの実際の描画が行われます。例えば
// Highlight pressed button if (m_selectedButton) { p->beginPath(); p->roundRect(m_views[m_selectedButton].rect, viewRadius); p->setLineWidth(2.0f * m_px); p->setStrokeStyle(m_theme.highlight()); p->stroke(); }
QCanvasPainter fill と stroke 呼び出しは、頂点、インデックス、ユニフォームデータ、QRhi-based draw 呼び出しを内部で準備します。コマンドのストリームは、PainterWindow::render() でendPaint() が呼び出されたときにフラッシュされます。ここでレンダー パスが関連するQRhiCommandBuffer に記録されます。
戻る前に、MainWindow::paint() は requestUpdate() を呼び出します。これはQWindow 関数で、ディスプレイの表示レートに同期して新しいフレームを要求します。これにより、ウィンドウのコンテンツが継続的に更新され、アニメートできるようになります。
詳細については、以下にリンクされている例のソースコードを参照してください。
© 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.