Qt QGraphicsView: paintEventの基本と描画のベストプラクティス

2025-05-27

paintEvent() とは何か

paintEvent(QPaintEvent *event) は、Qtのウィジェット(QWidget を継承するクラス)が自身を描画する際に呼び出されるイベントハンドラです。QGraphicsViewQWidget を継承しているため、この paintEvent() を持っています。

通常、paintEvent() は以下のような場合にシステムから自動的に呼び出されます。

  • ウィジェットのサイズが変更されたとき
  • ウィジェットの一部または全体が再描画される必要があるとき(例えば、他のウィンドウに隠されていた部分が表示されるようになった場合や、update() または repaint() メソッドが呼び出された場合)
  • ウィジェットが初めて表示されるとき

QGraphicsView::paintEvent() の役割

しかし、QGraphicsView における paintEvent() の役割は、一般的な QWidget のそれとは少し異なります。

一般的な QWidget のサブクラスでは、paintEvent() をオーバーライドして QPainter オブジェクトを使い、直接ウィジェット上に図形を描画します。

一方、QGraphicsView は、その内部に保持している QGraphicsScene を表示することが主な目的です。そのため、QGraphicsViewpaintEvent() は、直接描画コードを書く場所としては推奨されません

QGraphicsView::paintEvent() のデフォルトの実装は、以下の処理を行います。

  1. 描画する領域(event->rect() または event->region() で指定される更新領域)を特定します。
  2. その領域に基づいて、QGraphicsScene の描画処理をトリガーします。具体的には、QGraphicsScene に含まれるアイテムのうち、表示されている部分や更新が必要な部分だけが効率的に再描画されるように調整し、QGraphicsItem::paint() メソッドを呼び出します。
  3. 必要に応じて、QGraphicsView 自体の背景やフレームなどの描画も行います。

つまり、QGraphicsView::paintEvent() は、QGraphicsScene の描画を管理・調整するための内部的なメカニズムとして機能します。

QGraphicsView でカスタム描画を行うには?

もし QGraphicsView 上にカスタムな描画を行いたい場合、通常は以下の方法が推奨されます。

  1. QGraphicsItem を継承したカスタムアイテムを作成する: これが最も推奨される方法です。QGraphicsItem を継承したクラスを作成し、その paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) メソッドをオーバーライドします。このメソッド内で QPainter を使用して描画を行うことで、Graphics View Frameworkの恩恵(座標変換、衝突検出、アイテムの選択など)を受けられます。作成したアイテムは QGraphicsScene::addItem() でシーンに追加します。

  2. QGraphicsScenedrawBackground()drawForeground() をオーバーライドする: シーン全体の背景や前景に描画したい場合、QGraphicsScene のサブクラスを作成し、drawBackground() または drawForeground() メソッドをオーバーライドします。これらのメソッドは QPainter を引数に取るため、ここでカスタム描画を行うことができます。

  3. QGraphicsViewdrawBackground()drawForeground() をオーバーライドする(非推奨/特殊なケース): QGraphicsView 自体の背景や前景に描画することも可能ですが、これはビューの座標系で描画されるため、シーンの座標系とは異なります。あまり一般的ではありませんが、ビュー固有の装飾などを描画する際に使用されることがあります。

QGraphicsView::paintEvent() を直接オーバーライドして QPainter で描画してしまうと、以下のような問題が発生する可能性があります。

  • Graphics View Frameworkの機能喪失: 衝突検出、アイテムのインタラクション(移動、拡大縮小、回転など)、アイテムの選択といったGraphics View Frameworkの便利な機能を活用しにくくなります。
  • 座標系の混同: QGraphicsViewpaintEvent() 内で描画すると、それはビューの座標系(ピクセル座標)で描画されます。しかし、QGraphicsScene 上のアイテムはシーンの座標系で管理されており、座標変換を手動で管理する必要が生じ、複雑になりがちです。
  • 非効率な描画: QGraphicsView の持つ効率的な描画最適化(部分的な更新、カリングなど)の恩恵を受けられなくなる可能性があります。


よくあるエラーと問題

    • 原因: paintEvent() をオーバーライドした際に、基底クラスの QGraphicsView::paintEvent(event); の呼び出しを忘れている。
    • 説明: QGraphicsView のデフォルトの paintEvent() は、内部で QGraphicsScene の描画をトリガーします。これを呼び出さないと、シーン内のアイテムが描画されません。カスタム描画を行う場合でも、基本的には基底クラスの paintEvent() を最初に呼び出すべきです。
    • トラブルシューティング: オーバーライドした paintEvent() の先頭で QGraphicsView::paintEvent(event); を呼び出すことを確認してください。
  1. パフォーマンスの低下(描画が遅い、カクつく)

    • 原因1: paintEvent() 内で重い処理(ファイルI/O、複雑な計算、非効率なループなど)を行っている。

    • 説明: paintEvent() は頻繁に呼び出される可能性があるため、ここで時間のかかる処理を行うと、UIの応答性が著しく低下します。

    • トラブルシューティング1: paintEvent() 内では描画に直接関係する処理のみを行い、他の重い処理は別スレッドやイベントループの外で行うようにリファクタリングします。

    • 原因2: QGraphicsView の描画最適化(クリッピング、カリング)を妨げている。

    • 説明: QGraphicsView は、画面に表示されている部分や更新が必要な部分だけを描画するような最適化を自動的に行います。paintEvent() を不適切にオーバーライドしたり、QGraphicsItemboundingRect() を正しく設定しなかったりすると、この最適化が働かず、不要な部分まで描画されてしまいます。

    • トラブルシューティング2:

      • QGraphicsItem を使用している場合、boundingRect() がそのアイテムの実際の描画領域を正確に返すようにしてください。大きすぎる boundingRect() は、不要な再描画を引き起こします。
      • QGraphicsItem::paint() 内で QPainter::setClipRect(option->exposedRect) を使用して、描画領域をクリッピングするのを忘れていないか確認してください。
  2. QPainter のエラーメッセージ ("Painter not active", "Widget painting can only begin as a result of a paintEvent.")

    • 原因: paintEvent() の外で QPainterQGraphicsView (または任意の QWidget) 上で直接使用しようとしている。
    • 説明: QPainter は、paintEvent() の内部、または paintEvent() から呼び出された関数内で、かつ QPainter のコンストラクタに QPaintDevice (通常は this または viewport()) を渡す形で使用される必要があります。それ以外の場所で QPainter をアクティブにしようとすると、このエラーが発生します。
    • トラブルシューティング:
      • QGraphicsView に直接描画したい場合は、必ず paintEvent() をオーバーライドし、その中で QPainter painter(this->viewport()); のように QPainter を初期化してください。
      • 理想的には、QGraphicsItem::paint() メソッド内で描画を行い、QGraphicsView 上への直接描画は避けるべきです。
  3. 画面のちらつき(フリッカリング)

    • 原因: 描画処理が最適化されていない、またはダブルバッファリングが適切に設定されていない。
    • 説明: paintEvent() が頻繁に呼び出され、描画のたびに画面がクリアされてから再描画されると、ユーザーにはちらつきとして認識されます。
    • トラブルシューティング:
      • QGraphicsView はデフォルトでダブルバッファリングを有効にしているはずですが、念のため setViewportUpdateMode(QGraphicsView::FullViewportUpdate)setViewportUpdateMode(QGraphicsView::SmartViewportUpdate) の設定を確認してください。通常は SmartViewportUpdate が推奨されます。
      • カスタム描画を行っている場合、QPainter の描画設定(アンチエイリアシングなど)がパフォーマンスに影響していないか確認します。
      • QGraphicsSceneQGraphicsItemupdate() を不必要に頻繁に呼び出していないか確認します。変更があった部分だけを update() するように心がけます(例: update(boundingRect()))。
  4. QGraphicsItem の描画が期待通りにならない(重なり順、座標変換など)

    • 原因: QGraphicsView::paintEvent() 内で QPainter を使って直接描画している。
    • 説明: QGraphicsView は、QGraphicsItem の z-値(重なり順)、座標変換(拡大縮小、回転、移動)、衝突検出などを自動的に処理します。paintEvent() で直接描画すると、これらのGraphics View Frameworkの恩恵を受けられず、手動で管理する必要が生じ、バグの原因になります。
    • トラブルシューティング:
      • カスタム描画は必ず QGraphicsItem のサブクラスを作成し、その paint() メソッドをオーバーライドして行ってください。
      • アイテムの座標は常にシーン座標で考え、ビューの座標系を意識しないようにします。ビューは自動的にシーン座標からビュー座標への変換を行います。
  5. paintEvent() が呼び出されない

    • 原因: ウィジェットに再描画が必要であるというシグナルが送られていない。
    • 説明: paintEvent() は、Qtのイベントループによって自動的に呼び出されますが、そのためにはウィジェットが「無効(invalid)」状態になり、再描画が必要であるとマークされる必要があります。
    • トラブルシューティング:
      • ウィジェットの内容を変更した場合は、必ず update() または repaint() メソッドを呼び出してください。
        • update(): 非同期で、次のイベントループの機会に再描画をスケジュールします。複数の update() 呼び出しはマージされ、効率的です。
        • repaint(): 同期で、即座に再描画を行います。緊急の場合以外は update() が推奨されます。
      • QGraphicsItem の位置や見た目を変更した場合は、そのアイテムの update() メソッドを呼び出してください。
  • Qt Forum / Stack Overflow: 多くの開発者が同様の問題に遭遇しています。Qtの公式フォーラムやStack Overflowで検索することで、解決策が見つかることが多いです。
  • 最小限の再現コード: 問題が発生した場合、できるだけ最小限のコードでその問題を再現する試みは、原因特定に非常に役立ちます。
  • Qt Debugging Toolsの利用: Qt Creatorには、Qt Quick ProfilerなどのGUIパフォーマンスを分析するツールがあります。これらを活用して、描画ボトルネックを特定します。
  • デバッグ出力の活用: paintEvent() の中や、描画に関わる重要な場所で qDebug() を使ってメッセージを出力し、いつ、どれくらいの頻度で paintEvent() が呼び出されているか、描画にどれくらいの時間がかかっているかなどを確認します。


前述の通り、QGraphicsView::paintEvent() を直接オーバーライドして描画を行うことは、特殊なケースを除いて推奨されません。その代わりに、Graphics View Frameworkの意図する設計に沿って、QGraphicsItemQGraphicsScenepaint() メソッドをオーバーライドする方法が一般的です。

QGraphicsItem を継承してカスタム描画を行う (推奨)

これは、Graphics View Frameworkでグラフィカルな要素を描画する最も一般的で推奨される方法です。

MyRectItem.h

#ifndef MYRECTITEM_H
#define MYRECTITEM_H

#include <QGraphicsItem>
#include <QPainter>

class MyRectItem : public QGraphicsItem
{
public:
    MyRectItem(const QRectF& rect, QGraphicsItem* parent = nullptr);

    // QGraphicsItemを継承する場合、この2つの純粋仮想関数は必須
    QRectF boundingRect() const override;
    void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = nullptr) override;

private:
    QRectF m_rect;
    QColor m_color;
};

#endif // MYRECTITEM_H

MyRectItem.cpp

#include "MyRectItem.h"
#include <QDebug> // デバッグ出力用

MyRectItem::MyRectItem(const QRectF& rect, QGraphicsItem* parent)
    : QGraphicsItem(parent),
      m_rect(rect),
      m_color(Qt::blue) // デフォルトの色
{
    // アイテムがクリック可能であることを示すフラグ
    setFlag(ItemIsSelectable);
    setFlag(ItemIsMovable);
}

QRectF MyRectItem::boundingRect() const
{
    // アイテムの描画領域を正確に返す。
    // これが不正確だと、描画のちらつきや不要な再描画の原因になる。
    return m_rect;
}

void MyRectItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
    Q_UNUSED(widget); // この例では使用しない

    // デバッグ出力 (描画が呼ばれていることを確認)
    qDebug() << "Painting MyRectItem at" << m_rect;

    // クリッピング設定: 描画領域をoption->exposedRectに制限することで、
    // 不要な描画を避けてパフォーマンスを向上させる。
    painter->setClipRect(option->exposedRect);

    // 選択されている場合は色を変える
    if (option->state & QStyle::State_Selected) {
        painter->setBrush(QBrush(m_color.darker(150))); // 暗くする
    } else {
        painter->setBrush(QBrush(m_color));
    }

    // 枠線の設定
    painter->setPen(QPen(Qt::black, 2));

    // 長方形を描画
    painter->drawRect(m_rect);

    // テキストを描画 (シーン座標)
    painter->setPen(Qt::white);
    painter->drawText(m_rect, Qt::AlignCenter, "Hello Qt!");
}

使用例 (main.cpp または MainWindow クラス)

#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>
#include "MyRectItem.h" // 作成したカスタムアイテム

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // シーンを作成
    QGraphicsScene scene;
    scene.setSceneRect(0, 0, 800, 600); // シーンの論理的なサイズ

    // カスタムアイテムをいくつか作成してシーンに追加
    MyRectItem* rect1 = new MyRectItem(QRectF(50, 50, 100, 100));
    rect1->setPos(0, 0); // シーン上の位置
    scene.addItem(rect1);

    MyRectItem* rect2 = new MyRectItem(QRectF(0, 0, 80, 120));
    rect2->setPos(200, 100);
    scene.addItem(rect2);

    // ビューを作成し、シーンを設定
    QGraphicsView view(&scene);
    view.setRenderHint(QPainter::Antialiasing); // アンチエイリアシングを有効にする
    view.setWindowTitle("Custom QGraphicsItem Example");
    view.resize(820, 620); // ビューのウィンドウサイズ
    view.show();

    return a.exec();
}

解説:

  • QGraphicsView は単に QGraphicsScene を表示する役割を担います。アイテムの描画はビューではなく、アイテム自身が行います。
  • option->exposedRect を使用して QPainter::setClipRect() を設定することで、実際に更新が必要な領域のみを描画し、描画パフォーマンスを向上させています。
  • paint() メソッド内で QPainter を使用して実際の描画を行います。ここで描画される座標は、アイテムのローカル座標系です。
  • boundingRect() は、そのアイテムが占める最小の矩形領域を返します。Qtはこの情報を使って、描画の最適化(どのアイテムを描画する必要があるか)を行います。正確な boundingRect() はパフォーマンスに非常に重要です。
  • MyRectItemQGraphicsItem を継承し、boundingRect()paint() をオーバーライドしています。

シーン全体の背景や前景に描画したい場合に使用します。グリッド線や背景画像など、シーン全体に関わる描画に適しています。

MyGraphicsScene.h

#ifndef MYGRAPHICSSCENE_H
#define MYGRAPHICSSCENE_H

#include <QGraphicsScene>
#include <QPainter>

class MyGraphicsScene : public QGraphicsScene
{
public:
    MyGraphicsScene(QObject* parent = nullptr);

protected:
    void drawBackground(QPainter* painter, const QRectF& rect) override;
    void drawForeground(QPainter* painter, const QRectF& rect) override;
};

#endif // MYGRAPHICSSCENE_H

MyGraphicsScene.cpp

#include "MyGraphicsScene.h"
#include <QDebug>

MyGraphicsScene::MyGraphicsScene(QObject* parent)
    : QGraphicsScene(parent)
{
}

void MyGraphicsScene::drawBackground(QPainter* painter, const QRectF& rect)
{
    Q_UNUSED(rect); // この例ではrect全体に描画

    // デバッグ出力
    qDebug() << "Drawing scene background";

    // シーンの背景色を設定
    painter->fillRect(sceneRect(), Qt::lightGray);

    // グリッド線を描画 (シーン座標)
    qreal gridSize = 20;
    QPen gridPen(Qt::darkGray, 0.5);
    painter->setPen(gridPen);

    for (qreal x = sceneRect().left(); x < sceneRect().right(); x += gridSize) {
        painter->drawLine(QPointF(x, sceneRect().top()), QPointF(x, sceneRect().bottom()));
    }
    for (qreal y = sceneRect().top(); y < sceneRect().bottom(); y += gridSize) {
        painter->drawLine(QPointF(sceneRect().left(), y), QPointF(sceneRect().right(), y));
    }
}

void MyGraphicsScene::drawForeground(QPainter* painter, const QRectF& rect)
{
    Q_UNUSED(rect);

    // デバッグ出力
    qDebug() << "Drawing scene foreground";

    // シーンの四隅にテキストを描画 (シーン座標)
    painter->setPen(QPen(Qt::red, 2));
    painter->setFont(QFont("Arial", 16));
    painter->drawText(sceneRect().topLeft() + QPointF(10, 20), "Top-Left");
    painter->drawText(sceneRect().topRight() + QPointF(-80, 20), "Top-Right");
    painter->drawText(sceneRect().bottomLeft() + QPointF(10, -10), "Bottom-Left");
    painter->drawText(sceneRect().bottomRight() + QPointF(-100, -10), "Bottom-Right");
}

使用例 (main.cpp または MainWindow クラス)

#include <QApplication>
#include <QGraphicsView>
#include "MyGraphicsScene.h" // 作成したカスタムシーン
#include "MyRectItem.h"      // 必要であればカスタムアイテムも追加

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // カスタムシーンを作成
    MyGraphicsScene* scene = new MyGraphicsScene();
    scene->setSceneRect(0, 0, 800, 600); // シーンの論理的なサイズ

    // (オプション) カスタムアイテムをシーンに追加
    MyRectItem* rect = new MyRectItem(QRectF(150, 150, 200, 100));
    scene->addItem(rect);

    // ビューを作成し、シーンを設定
    QGraphicsView view(scene);
    view.setRenderHint(QPainter::Antialiasing);
    view.setWindowTitle("Custom QGraphicsScene Background/Foreground");
    view.resize(820, 620);
    view.show();

    return a.exec();
}

解説:

  • 描画は常にシーン座標系で行われます。
  • これらのメソッドは、ビューに表示されているシーンの部分を示す rect 引数を受け取ります。この rect を利用して、必要な部分だけを描画することでパフォーマンスを最適化できます。
  • MyGraphicsSceneQGraphicsScene を継承し、drawBackground()drawForeground() をオーバーライドしています。

この方法は、ビューポート(QGraphicsView の表示領域)に直接、シーンとは独立した描画を行いたい場合に限定されます。例えば、ビューの上にデバッグ情報や特別なUI要素をオーバーレイ表示するような場合です。しかし、ほとんどのケースでは QGraphicsItemQGraphicsScene を使うべきです。

MyGraphicsView.h

#ifndef MYGRAPHICSVIEW_H
#define MYGRAPHICSVIEW_H

#include <QGraphicsView>
#include <QPainter>
#include <QPaintEvent>

class MyGraphicsView : public QGraphicsView
{
    Q_OBJECT // QObjectを継承しているのでQ_OBJECTマクロが必要
public:
    MyGraphicsView(QGraphicsScene* scene, QWidget* parent = nullptr);

protected:
    // paintEventをオーバーライド
    void paintEvent(QPaintEvent* event) override;
};

#endif // MYGRAPHICSVIEW_H

MyGraphicsView.cpp

#include "MyGraphicsView.h"
#include <QDebug>

MyGraphicsView::MyGraphicsView(QGraphicsScene* scene, QWidget* parent)
    : QGraphicsView(scene, parent)
{
}

void MyGraphicsView::paintEvent(QPaintEvent* event)
{
    // !!! 重要: 基底クラスのpaintEventを必ず呼び出す !!!
    // これを忘れると、QGraphicsSceneのアイテムが描画されません。
    QGraphicsView::paintEvent(event);

    // ここからがMyGraphicsView独自の描画
    // QPainterはviewport()に対して描画する
    QPainter painter(this->viewport());

    // デバッグ出力 (このpaintEventが呼ばれていることを確認)
    qDebug() << "Custom MyGraphicsView::paintEvent called.";

    // ビューポートの中央に赤い円を描画 (ビューポート座標)
    painter.setPen(QPen(Qt::red, 3));
    painter.setBrush(Qt::NoBrush);
    painter.drawEllipse(rect().center(), 50, 50); // ビューの中心に半径50の円

    // ビューポートの右下隅にテキストを描画 (ビューポート座標)
    painter.setPen(Qt::darkGreen);
    painter.setFont(QFont("Consolas", 14));
    painter.drawText(rect().bottomRight() - QPoint(150, 30), "View Overlay Text");

    // 更新が必要な領域に描画を制限することも可能
    // painter.setClipRect(event->rect());
    // (QGraphicsView::paintEventが既に適切なクリッピングを設定しているため、
    // ここで再度設定する必要はないことが多いですが、理解のために記述)
}

使用例 (main.cpp または MainWindow クラス)

#include <QApplication>
#include <QGraphicsScene>
#include "MyGraphicsView.h" // 作成したカスタムビュー
#include "MyRectItem.h"     // 必要であればカスタムアイテムも追加

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QGraphicsScene scene;
    scene.setSceneRect(0, 0, 800, 600);

    // アイテムをシーンに追加
    MyRectItem* rect = new MyRectItem(QRectF(100, 100, 150, 150));
    scene.addItem(rect);

    // カスタムビューを作成し、シーンを設定
    MyGraphicsView view(&scene);
    view.setRenderHint(QPainter::Antialiasing);
    view.setWindowTitle("Custom QGraphicsView::paintEvent Example");
    view.resize(820, 620);
    view.show();

    return a.exec();
}

解説:

  • ここで描画される座標はビューポートのピクセル座標QGraphicsView ウィジェットの左上隅が (0,0))です。シーンの座標系とは異なりますので注意が必要です。
  • その後の描画は、QGraphicsView のビューポート(表示されている実際のピクセル領域)に対して行われます。したがって、QPainter(this->viewport()) のように QPainter を初期化します。
  • 最も重要なのは、QGraphicsView::paintEvent(event); を必ず最初に呼び出すことです。 これにより、シーンのアイテムが通常通り描画されます。
  • MyGraphicsViewQGraphicsView を継承し、paintEvent() をオーバーライドしています。


主な代替方法は以下の3つです。

QGraphicsItem::paint() をオーバーライドする (最も推奨)

これは、QGraphicsView 上に表示される具体的なグラフィック要素を作成するための最も推奨される方法です。あらゆる形状、画像、テキスト、カスタムウィジェットなどを表現できます。

  • 注意点: boundingRect() を正確に実装することがパフォーマンス上非常に重要です。
  • 用途:
    • カスタムな図形(多角形、曲線など)
    • 特定の画像やテキストの配置
    • ユーザーインタラクションが必要な要素(ボタン、スライダーの視覚化など)
    • グラフのノードやエッジ
  • 利点:
    • シーン座標系での描画: アイテムはシーンの論理的な座標系で描画されるため、QGraphicsView のズームや回転といった変換を自動的に引き継ぎます。
    • 描画の最適化: QGraphicsItem は自身の描画領域 (boundingRect()) をQtに伝えることで、表示されている部分だけを描画する「カリング」や「部分更新」といった最適化が自動的に適用されます。
    • インタラクション: 移動、回転、拡大縮小、選択、衝突検出など、QGraphicsItem が提供する豊富な機能やイベントハンドラ (mousePressEvent(), hoverEnterEvent() など) を利用できます。
    • 階層構造: アイテムを親子関係にすることで、複雑なグラフィックを整理し、親アイテムの変換が子アイテムに自動的に適用される階層構造を作成できます。

QGraphicsScene::drawBackground() / QGraphicsScene::drawForeground() をオーバーライドする

シーン全体の背景や前景に描画したい場合に利用します。アイテムとは独立した、シーン全体にわたる描画に適しています。

  • 注意点: これらのメソッド内で、シーン内の個々のアイテムの状態に基づいて複雑な描画を行うのは避けるべきです。アイテム固有の描画は QGraphicsItem::paint() で行うべきです。
  • 用途:
    • カスタムのグリッド線
    • シーン全体の背景画像やグラデーション
    • シーンの寸法ガイドや枠線
    • デバッグ用のオーバーレイ情報(例: シーンの座標軸)
  • 利点:
    • シーン座標系での描画: QGraphicsItem と同様に、シーンの論理的な座標系で描画されるため、ビューの変換に自動的に対応します。
    • 効率的な描画: rect 引数によって、ビューに表示されている、あるいは更新が必要なシーンの領域のみを描画できます。
    • シーン全体の装飾: シーン全体のグリッド線、背景画像、透かし、デバッグ情報などを描画するのに適しています。

より高度な描画制御が必要な場合や、特定のQGraphicsViewインスタンスに依存する描画を行いたい場合に検討されます。

代替方法描画座標系主な用途特徴
QGraphicsItem::paint()シーン座標個々のグラフィック要素、インタラクティブなオブジェクト最も推奨。自動的な変換、最適化、インタラクション機能。 boundingRect() が重要。
QGraphicsScene::drawBackground() / drawForeground()シーン座標シーン全体の背景/前景、グリッド線などシーン全体にわたる装飾。ビューの変換に追従。
QGraphicsView::drawBackground() / drawForeground()ビューポート座標ビュー固有のオーバーレイ、装飾ビューのピクセル座標で描画。シーンの変換とは独立。
カスタム QWidget をビューポートとして設定ビューポート座標QWidget の描画機能を活用したい場合低レベル。特殊なケース。
QGraphicsView の上に別の QWidget を重ねるウィジェット固有UI要素の配置、コントロール完全に独立したUIレイヤー。