Qtプログラミング必見!invalidateScene()のエラーとトラブルシューティング
QGraphicsView::invalidateScene()
は、QtのGraphics View Frameworkにおいて、QGraphicsView
が表示しているシーン(QGraphicsScene
)の再描画を強制するための関数です。
もう少し詳しく言うと、この関数を呼び出すと、QGraphicsView
は現在表示しているシーンの全てのキャッシュされた描画内容を無効化し、次回描画時にシーン全体を最初から描き直すようにスケジューリングします。
どのような時に使うのか?
通常、QGraphicsScene
内のアイテム(QGraphicsItem
)が変更された場合、そのアイテム自身や QGraphicsScene
が自動的に再描画をスケジューリングします。しかし、以下のようなケースでは、invalidateScene()
を明示的に呼び出す必要がある場合があります。
-
シーンの背景や前景が変更された場合
QGraphicsScene
のdrawBackground()
やdrawForeground()
をオーバーライドしてカスタム描画を行っており、その描画内容に影響を与えるような変更(例えば、背景画像の差し替え、グリッドの表示設定変更など)があった場合、invalidateScene()
を呼び出すことでビューにその変更を反映させることができます。 -
ビューのキャッシュモードを使用している場合
QGraphicsView
は描画パフォーマンス向上のために、シーンの一部または全体をキャッシュする機能を持っています(QGraphicsView::setCacheMode()
)。キャッシュされた内容に変更がない場合でも、キャッシュが無効化されないと新しい描画が反映されないことがあります。このような場合にinvalidateScene()
を使用してキャッシュを強制的に無効化し、再描画を促します。 -
予期せぬ描画の不整合
ごく稀に、QGraphicsScene
やQGraphicsView
が自動的に再描画すべき変更を検知できない、または描画が正しく更新されない場合があります。このようなデバッグ時や特定の条件下で、手動でシーン全体をリフレッシュするために使用されることがあります。
引数について
invalidateScene()
にはオーバーロードがあり、引数なしの invalidateScene()
の他に、const QRectF &rect
と QGraphicsScene::SceneLayers layers
を引数に取るものがあります。
-
invalidateScene(const QRectF &rect = QRectF(), QGraphicsScene::SceneLayers layers = QGraphicsScene::AllLayers)
指定したrect
(矩形領域) 内の、指定したlayers
(レイヤー) のキャッシュのみを無効化し、再描画をスケジューリングします。これによって、変更があった部分のみを効率的に再描画することができます。rect
を省略するとシーン全体、layers
を省略すると全てのレイヤーが対象となります。 -
invalidateScene() (引数なし)
シーン全体のキャッシュを無効化し、全体を再描画します。
注意点
invalidateScene()
は、シーンの再描画を強制する強力なツールですが、誤って使用するとパフォーマンスの問題を引き起こしたり、期待通りの描画結果が得られなかったりすることがあります。
パフォーマンスの問題(頻繁な呼び出し)
エラー/症状
- 特に、シーン内のアイテム数が多い場合や、複雑な描画が行われている場合に顕著。
- CPU使用率が高い。
- ビューの描画が遅い、カクつく。
原因
invalidateScene()
はシーン全体を再描画するため、頻繁に呼び出すとシステムに大きな負荷をかけます。特に、アニメーションのループ内で毎フレーム呼び出す、またはアイテムの微細な変更ごとに呼び出すといった使い方は、パフォーマンスの低下を招きます。
トラブルシューティング
- QGraphicsView::setViewportUpdateMode() の調整
ビューポートの更新モード(FullViewportUpdate
,SmartViewportUpdate
など)もパフォーマンスに影響を与えます。適切に設定されているか確認してください。 - 部分的な無効化を利用する
invalidateScene(const QRectF &rect, QGraphicsScene::SceneLayers layers)
オーバーロードを使用して、変更があった特定の領域やレイヤーのみを無効化することで、描画範囲を最小限に抑え、パフォーマンスを向上させることができます。 - 本当に必要か確認する
ほとんどの場合、QGraphicsItem
のupdate()
やQGraphicsScene
のupdate()
がより適切です。これらの関数は、変更があった部分のみを再描画するよう最適化されています。背景や前景が大きく変更された場合、またはビューのキャッシュモードを使用している場合など、本当にシーン全体を無効化する必要がある場合にのみinvalidateScene()
を使用してください。
期待通りの再描画が行われない(古い描画が残る)
エラー/症状
- 特定の
QGraphicsItem
の変更が反映されない(ただし、これは通常invalidateScene()
の問題ではありません)。 - ビューのキャッシュモードを使用しているときに、描画が更新されない。
- シーンの背景や前景を変更したのに、ビューに反映されない。
原因
QGraphicsScene::drawBackground()
やdrawForeground()
の中で、描画内容が実際には変更されていない、または条件によっては描画されないロジックになっている。invalidateScene()
ではなく、もっと限定的なupdate()
などが必要なケース。QGraphicsView
のキャッシュモードが原因で、古い描画が残っている。invalidateScene()
が呼び出されていない、または不適切なタイミングで呼び出されている。
トラブルシューティング
- アイテムの更新
特定のアイテムの変更が反映されない場合は、そのアイテムのupdate()
メソッドを呼び出すのが適切です。invalidateScene()
は主にシーン全体の背景・前景やキャッシュされたビューの更新に使用されます。 - QGraphicsScene::drawBackground() / drawForeground() のデバッグ
これらの仮想関数をオーバーライドしている場合、QPainter
の設定や描画ロジックが期待通りに動作しているか、デバッガを使って確認します。 - キャッシュモードの確認
QGraphicsView::setCacheMode()
をNoCache
に設定して、キャッシュが原因であるかテストします。もしNoCache
で問題が解決するなら、キャッシュの無効化が不十分であることが原因です。その場合、invalidateScene()
の呼び出し方(引数なしで全体を無効化するか、引数付きで特定のレイヤーを無効化するか)を検討し直してください。 - invalidateScene() の呼び出しを確認
シーンの背景・前景を変更するコード(例:scene->setBackgroundBrush(...)
の後など)の直後でview->invalidateScene()
が呼び出されているか確認します。
不適切な描画領域の指定
エラー/症状
- 描画されるべき部分が描画されず、空白になったり、古い描画が残ったりする。
invalidateScene(rect, layers)
を使用しているが、一部の変更が反映されない。
原因
rect
で指定された領域が、実際に変更された内容を完全に含んでいないためです。
- layers の確認
どのレイヤー(QGraphicsScene::BackgroundLayer
,QGraphicsScene::ForegroundLayer
,QGraphicsScene::ItemLayer
など)が変更されたかを正しく指定しているか確認します。 - rect の正確な計算
変更された領域を正確にカバーするようにrect
を計算します。必要に応じて、変更された複数の領域を結合するQRectF::united()
を使用することも検討します。
デバッグのヒント
- シンプルな例で再現
複雑なアプリケーションで問題が発生した場合、最小限のコードで問題が再現できるか試すことで、原因の特定が容易になります。 - Qt Creator のデバッガ
Qt Creator のデバッガを使用して、コードの実行フローをステップ実行し、invalidateScene()
がいつ呼び出されるか、またその際の変数の状態を確認します。 - qDebug() でログ出力
invalidateScene()
が呼び出されたタイミングや、rect
の値などをqDebug()
で出力し、期待通りに動作しているか確認します。
invalidateScene()
は主に、QGraphicsScene
の背景や前景の描画内容が変更された場合、または QGraphicsView
のキャッシュモードを有効にしている場合に、ビューの表示を強制的に更新するために使用されます。
例1: シーンの背景色を変更し、ビューを更新する
この例では、ボタンがクリックされるたびにシーンの背景色を変更し、invalidateScene()
を呼び出してビューの再描画を強制します。
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#include <QBrush>
#include <QDebug>
#include <QRandomGenerator> // C++11以降
class MyGraphicsView : public QGraphicsView
{
Q_OBJECT
public:
MyGraphicsView(QGraphicsScene *scene, QWidget *parent = nullptr)
: QGraphicsView(scene, parent)
{
// ビューのキャッシュモードを有効にする(パフォーマンス向上のため)
// invalidateScene() が特に効果を発揮する状況を作る
setCacheMode(CacheBackground);
setViewportUpdateMode(FullViewportUpdate); // 全体を更新
}
public slots:
void changeBackgroundColor()
{
if (!scene()) return;
// ランダムな色を生成
QColor randomColor = QColor(QRandomGenerator::global()->bounded(256),
QRandomGenerator::global()->bounded(256),
QRandomGenerator::global()->bounded(256));
scene()->setBackgroundBrush(randomColor);
qDebug() << "背景色を変更しました: " << randomColor.name();
// ここで invalidateScene() を呼び出すことで、キャッシュされた背景が無効化され、
// 新しい背景色でシーン全体が再描画されます。
// 引数なしの場合、シーン全体を無効化し、全レイヤーを再描画します。
invalidateScene();
// もしキャッシュモードが有効でない場合、または背景の描画がQGraphicsScene::drawBackground()で
// カスタム実装されている場合は、scene()->update()だけでは背景が更新されないことがあります。
// そのため、確実に更新するには invalidateScene() が必要になります。
// ただし、setBackgroundBrush()自体は通常、自動的にシーンの更新をトリクエストします。
// ここでの invalidateScene() は、特にCacheBackgroundなどのキャッシュモードで、
// 描画が更新されない場合に確実性を高めるためのものです。
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// シーンを作成
QGraphicsScene scene;
scene.setSceneRect(-200, -200, 400, 400); // シーンの範囲を設定
// ビューを作成
MyGraphicsView view(&scene);
view.setWindowTitle("invalidateScene() の例");
view.setRenderHint(QPainter::Antialiasing); // アンチエイリアス有効化
// シーンにアイテムを追加
scene.addRect(-50, -50, 100, 100, QPen(Qt::blue), QBrush(Qt::cyan));
scene.addEllipse(50, 50, 80, 80, QPen(Qt::red), QBrush(Qt::magenta));
// レイアウトとボタン
QVBoxLayout *layout = new QVBoxLayout();
QPushButton *button = new QPushButton("背景色を変更");
layout->addWidget(button);
layout->addWidget(&view);
QWidget window;
window.setLayout(layout);
window.resize(600, 500);
window.show();
// ボタンとスロットを接続
QObject::connect(button, &QPushButton::clicked, &view, &MyGraphicsView::changeBackgroundColor);
return a.exec();
}
#include "main.moc" // mocファイルをインクルードすることで、スロットが機能します
解説
invalidateScene()
を呼び出すことで、ビューはキャッシュされていた背景の描画を破棄し、新しい背景色でシーン全体を再描画します。 これにより、背景色の変更がビューに即座に反映されます。もしinvalidateScene()
を呼び出さなかった場合、setBackgroundBrush()
が自動的にシーンの更新をトリガーしますが、キャッシュモードによっては即座に反映されない可能性があります。changeBackgroundColor()
スロットでは、scene()->setBackgroundBrush()
でシーンの背景色を変更しています。- コンストラクタで
setCacheMode(CacheBackground)
を呼び出し、背景の描画をキャッシュするように設定しています。これにより、invalidateScene()
の効果がより明確になります。 MyGraphicsView
クラスはQGraphicsView
を継承しています。
例2: カスタム QGraphicsScene::drawBackground()
を更新する
QGraphicsScene::drawBackground()
をオーバーライドしてカスタムな背景を描画している場合、その描画ロジックに影響を与えるデータが変更されたときに invalidateScene()
を呼び出す必要があります。
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#include <QBrush>
#include <QPainter>
#include <QDebug>
// カスタムシーンクラス
class CustomScene : public QGraphicsScene
{
Q_OBJECT
public:
CustomScene(QObject *parent = nullptr)
: QGraphicsScene(parent), m_gridDensity(10) // グリッドの密度を初期化
{
setSceneRect(-200, -200, 400, 400);
}
void setGridDensity(int density)
{
if (density != m_gridDensity) {
m_gridDensity = density;
qDebug() << "グリッド密度を変更: " << m_gridDensity;
// グリッド密度が変わったので、背景を再描画する必要がある
// invalidate() を呼び出すことで、シーンの背景レイヤーが無効化され、
// ビューによって再描画がスケジューリングされます。
// QGraphicsView::invalidateScene() は QGraphicsScene::invalidate() を呼び出します。
invalidate(sceneRect(), QGraphicsScene::BackgroundLayer);
}
}
protected:
// 背景のカスタム描画
void drawBackground(QPainter *painter, const QRectF &rect) override
{
QGraphicsScene::drawBackground(painter, rect); // デフォルトの背景色を描画
// グリッドを描画
qreal left = rect.left();
qreal right = rect.right();
qreal top = rect.top();
qreal bottom = rect.bottom();
QPen gridPen(Qt::lightGray, 0);
painter->setPen(gridPen);
// 垂直線
for (qreal x = qRound(left / m_gridDensity) * m_gridDensity; x < right; x += m_gridDensity) {
painter->drawLine(QPointF(x, top), QPointF(x, bottom));
}
// 水平線
for (qreal y = qRound(top / m_gridDensity) * m_gridDensity; y < bottom; y += m_gridDensity) {
painter->drawLine(QPointF(left, y), QPointF(right, y));
}
}
private:
int m_gridDensity;
};
class MainWindow : public QWidget
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr) : QWidget(parent)
{
scene = new CustomScene(this);
view = new QGraphicsView(scene, this);
view->setRenderHint(QPainter::Antialiasing);
// キャッシュモードを有効にする (この例では背景にのみ影響)
view->setCacheMode(QGraphicsView::CacheBackground);
QPushButton *increaseDensityButton = new QPushButton("グリッド密度を増やす");
QPushButton *decreaseDensityButton = new QPushButton("グリッド密度を減らす");
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(increaseDensityButton);
layout->addWidget(decreaseDensityButton);
layout->addWidget(view);
connect(increaseDensityButton, &QPushButton::clicked, this, &MainWindow::increaseGridDensity);
connect(decreaseDensityButton, &QPushButton::clicked, this, &MainWindow::decreaseGridDensity);
// シーンにアイテムを追加
scene->addRect(-50, -50, 100, 100, QPen(Qt::blue), QBrush(Qt::cyan));
}
private slots:
void increaseGridDensity()
{
scene->setGridDensity(scene->property("gridDensity").toInt() + 5);
}
void decreaseGridDensity()
{
int currentDensity = scene->property("gridDensity").toInt();
if (currentDensity > 5) {
scene->setGridDensity(currentDensity - 5);
}
}
private:
CustomScene *scene;
QGraphicsView *view;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.resize(600, 500);
w.show();
return a.exec();
}
#include "main.moc"
解説
MainWindow
クラスでは、ボタンを押すとsetGridDensity()
を呼び出し、グリッドの密度を変更しています。invalidate(sceneRect(), QGraphicsScene::BackgroundLayer);
が重要な部分です。QGraphicsScene::invalidate()
はQGraphicsView::invalidateScene()
と似ていますが、シーン自身から呼び出すことができます。この場合、変更されたのは背景レイヤーだけなので、BackgroundLayer
を指定して、そのレイヤーのキャッシュのみを無効化し、効率的に再描画を促しています。これにより、ビューは背景だけを更新します。setGridDensity()
メソッドでは、グリッドの密度を変更しています。CustomScene
はQGraphicsScene
を継承し、drawBackground()
をオーバーライドしてグリッドを描画しています。
例3: invalidateScene()
を引数なしで使用するケース(キャッシュされた内容全体のリセット)
この例では、ビューの変換(ズームやパン)後に、キャッシュされた内容をすべてリセットしたい場合を想定します。
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#include <QGraphicsRectItem>
#include <QDebug>
#include <QWheelEvent> // ホイールイベントを捕捉するため
class ZoomableView : public QGraphicsView
{
Q_OBJECT
public:
ZoomableView(QGraphicsScene *scene, QWidget *parent = nullptr)
: QGraphicsView(scene, parent)
{
// 高度なキャッシュモードを有効にする(invalidateScene() の効果が明確になる)
setCacheMode(CacheNone); // デフォルトではキャッシュなし
setViewportUpdateMode(FullViewportUpdate); // 全体を更新
// setCacheMode(CacheBackground | CacheNone); // QGraphicsView::CacheNoneとQGraphicsView::CacheBackground/CacheItemsは排他的なので注意
// 実際には、QGraphicsView::CacheModeは個々のフラグの組み合わせではなく、指定されたモードのみが有効になります。
// CacheBackground は背景のキャッシュ、CacheItems はアイテムのキャッシュ、CacheNone はキャッシュなしです。
// ここでは、明示的に CacheNone に設定し、後で invalidateScene() を呼んだ場合に何が起こるかを示すためです。
// もし CacheBackground や CacheItems を有効にしている場合は、invalidateScene() の効果が大きくなります。
}
protected:
void wheelEvent(QWheelEvent *event) override
{
qreal scaleFactor = 1.15; // ズーム倍率
if (event->angleDelta().y() > 0) {
// スクロールアップ (ズームイン)
scale(scaleFactor, scaleFactor);
} else {
// スクロールダウン (ズームアウト)
scale(1.0 / scaleFactor, 1.0 / scaleFactor);
}
// ズーム後にビューの描画キャッシュを強制的に無効化し、再描画を促す
// 特に複雑な変換や最適化フラグを使用している場合、これにより表示の不整合を防げます。
// ただし、通常、QGraphicsView::scale() は自動的に更新をトリガーするため、
// 明示的な invalidateScene() は必須ではありませんが、特定の最適化設定や
// 描画の不整合が発生した場合に役立ちます。
invalidateScene(); // 引数なしでシーン全体を無効化
event->accept(); // イベントを処理済みとしてマーク
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene scene;
scene.setSceneRect(-200, -200, 400, 400);
// シーンに多数のアイテムを追加して、描画が複雑になる状況を作る
for (int i = 0; i < 50; ++i) {
QGraphicsRectItem *rectItem = new QGraphicsRectItem(QRandomGenerator::global()->bounded(-180, 180),
QRandomGenerator::global()->bounded(-180, 180),
QRandomGenerator::global()->bounded(20, 50),
QRandomGenerator::global()->bounded(20, 50));
rectItem->setPen(QPen(QColor(QRandomGenerator::global()->bounded(256),
QRandomGenerator::global()->bounded(256),
QRandomGenerator::global()->bounded(256))));
rectItem->setBrush(QBrush(QColor(QRandomGenerator::global()->bounded(256),
QRandomGenerator::global()->bounded(256),
QRandomGenerator::global()->bounded(256),
150))); // 半透明
scene.addItem(rectItem);
}
ZoomableView view(&scene);
view.setWindowTitle("invalidateScene() ズームの例");
view.setRenderHint(QPainter::Antialiasing);
view.setDragMode(QGraphicsView::ScrollHandDrag); // ドラッグでパンできるようにする
QVBoxLayout *layout = new QVBoxLayout();
layout->addWidget(&view);
QWidget window;
window.setLayout(layout);
window.resize(600, 500);
window.show();
return a.exec();
}
#include "main.moc"
- このケースでは、
QGraphicsView::scale()
は通常、自動的にビューの更新をトリガーするため、invalidateScene()
は厳密には必須ではありません。しかし、特定の描画最適化設定や、予期せぬ描画の不整合が発生した場合に、明示的にinvalidateScene()
を呼び出すことで、ビューのキャッシュを完全にリセットし、シーン全体を強制的に再描画させることができます。特に、QGraphicsView::setOptimizationFlags()
で複雑な描画最適化を行っている場合に役立つことがあります。 - ズーム操作 (
scale()
) の後、invalidateScene()
を呼び出しています。 ZoomableView
はwheelEvent()
をオーバーライドし、マウスホイールでズームできるようにしています。
QGraphicsItem::update() - 個々のアイテムの更新
これが最も一般的で推奨される方法です。特定の QGraphicsItem
の見た目や状態が変更された場合、そのアイテム自身に update()
を呼び出すことで、そのアイテムの描画領域のみを再描画するようビューに要求します。
- 引数
void QGraphicsItem::update(const QRectF &rect = QRectF())
: アイテムのローカル座標における指定された矩形領域を更新します。引数なしの場合はアイテム全体の境界矩形 (boundingRect()
) が更新されます。
- 利点
最も効率的です。必要な部分だけが再描画されるため、パフォーマンスへの影響が最小限に抑えられます。 - 使用例
アイテムの位置、サイズ、色、テキストなどのプロパティが変更された場合。アニメーションでアイテムが動く場合。
// 例: QGraphicsRectItem の色を変更し、更新
QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 100, 100);
scene->addItem(rectItem);
// 後で色を変更する場合
rectItem->setBrush(Qt::red);
rectItem->update(); // このアイテムの描画領域のみを更新
QGraphicsScene::update() - シーンの一部または全体の更新
QGraphicsScene
自体の変更(例: 背景色の変更、グリッドの描画内容の変更など)や、複数のアイテムに影響を与えるような広範囲な変更があった場合に、シーン側から更新を要求します。
- 引数
void QGraphicsScene::update(const QRectF &rect = QRectF())
: シーン座標における指定された矩形領域を更新します。引数なしの場合は、シーン全体の境界矩形 (sceneRect()
) が更新されます。
- 利点
invalidateScene()
よりも粒度が細かく、指定した領域のみを更新できるため、効率的です。
// 例: シーンの背景色を変更し、シーン全体を更新 (QGraphicsScene::setBackgroundBrush()自体も通常はupdateを呼び出す)
QGraphicsScene *scene = new QGraphicsScene();
scene->setBackgroundBrush(Qt::blue);
scene->update(); // シーン全体を更新要求
// 例: シーンの特定領域のみを更新
scene->update(10, 10, 50, 50); // シーン座標 (10,10) から (50,50) の範囲を更新
QGraphicsScene::invalidate() - シーンの特定のレイヤーの更新
これは QGraphicsView::invalidateScene()
の元となる QGraphicsScene
の関数で、シーンの描画キャッシュを無効化し、特定のレイヤー(背景、アイテム、前景)を再描画するよう要求します。QGraphicsView::invalidateScene()
は内部的にこれを使用します。
- 引数
void QGraphicsScene::invalidate(const QRectF &rect = QRectF(), QGraphicsScene::SceneLayers layers = QGraphicsScene::AllLayers)
: 指定された矩形領域とレイヤーのキャッシュを無効化し、再描画をスケジューリングします。
- 利点
update()
よりも強力で、キャッシュに依存する描画の不整合を解消できます。特定のレイヤーのみを対象にできるため、QGraphicsView::invalidateScene()
(引数なし) よりも効率的です。 - 使用例
QGraphicsScene::drawBackground()
やQGraphicsScene::drawForeground()
のカスタム描画内容が変更された場合に、キャッシュを無効化して再描画を強制したいとき。
// 例: カスタム背景が変更された際に背景レイヤーのみを更新
// (CustomScene::setGridDensity() の例で使ったもの)
void CustomScene::setGridDensity(int density)
{
if (density != m_gridDensity) {
m_gridDensity = density;
// 背景レイヤーのキャッシュを無効化し、再描画をトリガー
invalidate(sceneRect(), QGraphicsScene::BackgroundLayer);
}
}
QGraphicsView::viewport()->update() または repaint() - ビューポートの直接的な更新
QGraphicsView
のビューポート(通常は QWidget
)の update()
または repaint()
を呼び出すことで、ビューポートそのものを直接更新します。
- Qtドキュメントからのアドバイス
ほとんどの場合、QGraphicsItem::update()
やQGraphicsScene::update()
の方が推奨されます。ビューポートの直接更新は、Graphics View Framework の自動更新メカニズムでは対応できない稀なケースでのみ検討すべきです。 - 注意点
update()
はイベントループに再描画イベントをキューイングしますが、repaint()
は即座に再描画を行います。repaint()
はパフォーマンスに大きな影響を与えるため、特別な理由がない限り避けるべきです。 - 利点
最も直接的な方法ですが、Graphics View Framework の最適化をバイパスする可能性があります。 - 使用例
QGraphicsView
のレンダリング設定(例: アンチエイリアス)を変更した場合や、デバッグ目的でビューポート全体を強制的に再描画したい場合。
// 例: ビューポート全体を再描画 (推奨されないケースが多い)
view->viewport()->update(); // QGraphicsView::update() と同等
// または
view->viewport()->repaint(); // 即座に再描画 (非推奨)
どの方法を選ぶべきか?
- 緊急かつ全体的な再描画が必要で、パフォーマンスを犠牲にしてもよい場合
QGraphicsView::invalidateScene()
(引数なし) - シーンの特定領域の変更(キャッシュは問題ない場合)
QGraphicsScene::update(rect)
- シーンの背景/前景の変更(キャッシュを無効化したい場合)
QGraphicsScene::invalidate(rect, layers)
またはQGraphicsView::invalidateScene(rect, layers)
- アイテムの変更
QGraphicsItem::update()