Qt Widgets 6.0の新機能: QGraphicsItem::setCacheSize()でキャッシュサイズを制御


QGraphicsItem::setCacheMode()関数は、Qt Widgetsライブラリで提供されるグラフィックスアイテムのキャッシュモードを設定するために使用されます。キャッシュモードは、アイテムの描画パフォーマンスを向上させるために、アイテムのレンダリング結果をメモリに保存するかどうかを決定します。

キャッシュモードの種類

QGraphicsItem::setCacheMode()関数には、以下の4つのキャッシュモードを指定することができます。

  • BackgroundModeCache
    背景モードキャッシュを使用します。アイテムが移動または回転された場合、またはアイテムのコンテンツが変更された場合、またはアイテムの親アイテムが変更された場合にのみ、再描画されます。
  • ItemCoordinateCache
    アイテム座標キャッシュを使用します。アイテムのコンテンツが変更された場合にのみ、再描画されます。
  • DeviceCoordinateCache
    デバイス座標キャッシュを使用します。アイテムが移動または回転された場合、またはアイテムのコンテンツが変更された場合にのみ、再描画されます。
  • NoCache
    キャッシュを使用しません。アイテムが更新されるたびに、常に再描画されます。

キャッシュモードの選択

適切なキャッシュモードは、アイテムの使用状況によって異なります。一般的には、以下のガイドラインに従ってキャッシュモードを選択することができます。

  • 動的なアイテムまたはコンテンツが頻繁に変更されるアイテムの場合は、NoCacheまたはBackgroundModeCacheを使用します。
  • 静的でコンテンツが変更されないアイテムの場合は、DeviceCoordinateCacheまたはItemCoordinateCacheを使用します。

以下のコード例は、QGraphicsRectItemアイテムのキャッシュモードをDeviceCoordinateCacheに設定する方法を示しています。

QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
item->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
  • キャッシュモードは、アイテムのパフォーマンスに大きな影響を与える可能性があります。適切なキャッシュモードを選択することが重要です。
  • キャッシュモードを使用する場合は、アイテムのコンテンツが変更されたことをupdate()関数を使用して通知する必要があります。
  • キャッシュモードを変更すると、アイテムが再描画されます。
  • Qt Widgets 6.0以降では、QGraphicsItem::setCacheMode()関数に加えて、setCacheSize()関数を使用してキャッシュサイズを設定することもできます。
  • QGraphicsItem::setCacheMode()関数は、Qt Widgets 5.0以降で使用できます。


#include <QGraphicsItem>
#include <QGraphicsRectItem>

int main() {
  // QGraphicsSceneを作成
  QGraphicsScene scene;

  // QGraphicsRectItemを作成
  QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100));

  // アイテムのキャッシュモードをDeviceCoordinateCacheに設定
  item->setCacheMode(QGraphicsItem::DeviceCoordinateCache);

  // アイテムをシーンに追加
  scene.addItem(item);

  // ビューアを作成してシーンを表示
  QGraphicsView view(&scene);
  view.show();

  return 0;
}

このコードを実行すると、100x100ピクセルの矩形アイテムが表示されます。アイテムを移動または回転しても、再描画されることなくスムーズに表示されます。

例2: 動的なアイテム

以下のコード例は、QGraphicsEllipseItemアイテムを動的に作成し、NoCacheキャッシュモードを設定する方法を示しています。

#include <QGraphicsItem>
#include <QGraphicsEllipseItem>
#include <QTimer>

int main() {
  // QGraphicsSceneを作成
  QGraphicsScene scene;

  // QGraphicsEllipseItemを作成
  QGraphicsEllipseItem *item = new QGraphicsEllipseItem(QRectF(0, 0, 50, 50));

  // アイテムのキャッシュモードをNoCacheに設定
  item->setCacheMode(QGraphicsItem::NoCache);

  // アイテムをシーンに追加
  scene.addItem(item);

  // タイマーを作成
  QTimer timer;

  // タイマーが起動するたびにアイテムの位置を更新
  QObject::connect(&timer, &QTimer::timeout, [item]() {
    item->setPos(item->pos() + QPointF(1, 1));
  });

  // タイマーを10ミリ秒間隔で起動
  timer.start(10);

  // ビューアを作成してシーンを表示
  QGraphicsView view(&scene);
  view.show();

  return 0;
}

このコードを実行すると、50x50ピクセルの楕円アイテムが表示されます。アイテムは10ミリ秒ごとに1ピクセルずつ右下に移動します。アイテムが移動するたびに再描画されるため、スムーズなアニメーション効果が得られます。

例3: コンテンツが変更されるアイテム

以下のコード例は、QGraphicsTextItemアイテムを作成し、ItemCoordinateCacheキャッシュモードを設定し、アイテムのテキストコンテンツを定期的に更新する方法を示しています。

#include <QGraphicsItem>
#include <QGraphicsTextItem>
#include <QTimer>

int main() {
  // QGraphicsSceneを作成
  QGraphicsScene scene;

  // QGraphicsTextItemを作成
  QGraphicsTextItem *item = new QGraphicsTextItem("Hello, World!");

  // アイテムのキャッシュモードをItemCoordinateCacheに設定
  item->setCacheMode(QGraphicsItem::ItemCoordinateCache);

  // アイテムをシーンに追加
  scene.addItem(item);

  // タイマーを作成
  QTimer timer;

  // タイマーが起動するたびにアイテムのテキストコンテンツを更新
  QObject::connect(&timer, &QTimer::timeout, [item]() {
    static int counter = 0;
    item->setPlainText(QString("Hello, World! #%1").arg(counter++));
  });

  // タイマーを1秒間隔で起動
  timer.start(1000);

  // ビューアを作成してシーンを表示
  QGraphicsView view(&scene);
  view.show();

  return 0;
}

このコードを実行すると、「Hello, World!」というテキストが表示されます。テキストは1秒ごとに「Hello, World! #n」というように更新されます。アイテムのコンテンツが変更されるため、ItemCoordinateCacheキャッシュモードを使用すると、再描画回数を減らすことができます。



代替方法

  • カスタムレンダリングを使用:カスタムレンダリングを使用することで、アイテムをより効率的に描画することができます。
  • ハードウェアアクセラレーションを使用:ハードウェアアクセラレーションを使用することで、GPUを使用してアイテムをより速く描画することができます。
  • 描画品質を下げる:描画品質を下げることで、描画に必要な処理量を減らすことができます。
  • アイテムのサイズを小さく:アイテムのサイズを小さくすることで、描画に必要なピクセル数を減らすことができます。
  • アイテムのコンテンツを簡素化:アイテムのコンテンツを簡素化することで、描画に必要な処理量を減らすことができます。

各方法の詳細

  • カスタムレンダリングを使用:カスタムレンダリングを使用するには、以下の方法があります。
    • QPainterを使用してアイテムを直接描画する。
    • QGLWidgetまたはQVulkanWidgetを使用してOpenGLまたはVulkanを使用してアイテムを描画する。
  • ハードウェアアクセラレーションを使用:ハードウェアアクセラレーションを使用するには、以下の方法があります。
    • OpenGLを使用する。
    • Vulkanを使用する。
  • 描画品質を下げる:描画品質を下げるには、以下の方法があります。
    • 抗エイリアシングを無効にする。
    • 線幅を小さくする。
    • フォントサイズを小さくする。
  • アイテムのサイズを小さく:アイテムのサイズを小さくするには、以下の方法があります。
    • アイテムの必要最低限のサイズにトリミングする。
    • アイテムのスケールを変更する。
  • アイテムのコンテンツを簡素化:アイテムのコンテンツを簡素化するには、以下の方法があります。
    • 不要なラインや形状を削除する。
    • グラデーションやテクスチャの使用を減らす。
    • 画像の圧縮率を上げる。
  • 代替方法を使用すると、アイテムの外観や動作が変わる場合があります。
  • 代替方法を使用する前に、QGraphicsItem::setCacheMode()関数を使用するよりもパフォーマンスが向上するかどうかをテストする必要があります。
  • 上記の代替方法は、すべての状況で有効とは限りません。