Qt GUI の ScaledPixmapArgument::size を使ってアイコンを DPI に合わせてスマートにスケーリング


役割

  • "@nx" 高 DPI 構文の恩恵を受けられるようにします。
  • 高 DPI ディスプレイでアイコンがぼやけるのを防ぎます。
  • デバイスピクセル比に基づいて適切なサイズのピクセルマップを決定します。

構造

struct ScaledPixmapArgument {
  QIcon::Mode mode;
  QPixmap pixmap;
  qreal scale;
  QSize size;
  QIcon::State state;
};

メンバー変数

  • state: ピクセルマップの要求状態 (QIcon::State を参照)
  • size: ピクセルマップの要求サイズ
  • scale: ピクセルマップの要求スケール
  • pixmap: サイズ、モード、状態、スケールに最もよく一致するピクセルマップ (出力パラメータ)
  • mode: ピクセルマップの要求モード (QIcon::Mode を参照)

使用方法

ScaledPixmapArgument::size は、QIconEngine::virtual_hook() 関数の引数として使用されます。この関数は、アイコンエンジンがアイコンのピクセルマップを生成する方法をカスタマイズするために使用されます。

ScaledPixmapArgument::size を使用するには、以下の手順に従います。

  1. ScaledPixmapArgument 構造体のインスタンスを作成します。
  2. メンバー変数を設定します。
  3. QIconEngine::virtual_hook() 関数を呼び出します。

ScaledPixmapArgument arg;
arg.mode = QIcon::Normal;
arg.size = QSize(32, 32);
arg.scale = devicePixelRatio();

QPixmap pixmap = iconEngine->virtual_hook(QIconEngine::ScaledPixmapHook, arg);

この例では、32x32 ピクセルのサイズの、デバイスピクセル比に適したピクセルマップが生成されます。

  • ScaledPixmapArgument::size は、Qt 5.6 以降で使用できます。


#include <QIconEngine>
#include <QPixmap>
#include <QSize>

class MyIconEngine : public QIconEngine
{
public:
  virtual QPixmap virtual_hook(QIconEngine::IconHookType type,
                               const QIconEngine::IconParameter &param) override
  {
    if (type == QIconEngine::ScaledPixmapHook) {
      const ScaledPixmapArgument &arg = param.argument<ScaledPixmapArgument>();

      QPixmap pixmap;
      // ピクセルマップを生成する処理

      return pixmap;
    } else {
      return QIconEngine::virtual_hook(type, param);
    }
  }
};

int main()
{
  QIcon icon;
  icon.setEngine(new MyIconEngine());

  // アイコンを使用する処理

  return 0;
}
  • ピクセルマップを生成する処理は、アプリケーション固有の処理に置き換える必要があります。
  • ScaledPixmapArgument::size は、QIconEngine::ScaledPixmapHook タイプの引数として使用されます。
  • MyIconEngine::virtual_hook() 関数は、アイコンエンジンがアイコンのピクセルマップを生成する方法をカスタマイズするために使用されます。
  • このコードは、MyIconEngine という名前のアイコンエンジンを定義します。
  • ピクセルマップを生成する処理は、さまざまな方法で実装できます。たとえば、ファイルから読み込んだり、コードで生成したりできます。
  • このコードは、あくまでも例です。実際のアプリケーションでは、必要に応じて変更する必要があります。


QIcon::setThemeIcon 関数を使用する**

QIcon::setThemeIcon() 関数は、テーマからアイコンを取得するために使用できます。この関数は、デバイスピクセル比に適したピクセルマップを自動的に返します。

QIcon icon;
icon.setThemeIcon("application");

QIcon::fromTheme() 関数と QPixmap::scaled メソッドを使用する**

QIcon::fromTheme() 関数は、テーマからアイコンを取得するために使用できます。QPixmap::scaled() メソッドは、ピクセルマップをスケーリングするために使用できます。

QIcon icon;
QPixmap pixmap = QIcon::fromTheme("application").pixmap();
pixmap = pixmap.scaled(QSize(32, 32), Qt::KeepAspectRatio, Qt::SmoothTransformation);
icon.setPixmap(pixmap);

カスタムアイコンエンジンを使用する

カスタムアイコンエンジンを作成して、デバイスピクセル比に適したピクセルマップを生成することができます。これは、より高度なカスタマイズが必要な場合に役立ちます。

class MyIconEngine : public QIconEngine
{
public:
  virtual QPixmap virtual_hook(QIconEngine::IconHookType type,
                               const QIconEngine::IconParameter &param) override
  {
    if (type == QIconEngine::ScaledPixmapHook) {
      const ScaledPixmapArgument &arg = param.argument<ScaledPixmapArgument>();

      QPixmap pixmap;
      // ピクセルマップを生成する処理

      return pixmap;
    } else {
      return QIconEngine::virtual_hook(type, param);
    }
  }
};

int main()
{
  QIcon icon;
  icon.setEngine(new MyIconEngine());

  // アイコンを使用する処理

  return 0;
}

それぞれの方法の利点と欠点

方法利点欠点
QIcon::setThemeIcon()簡単カスタマイズ性が低い
QIcon::fromTheme() と QPixmap::scaled()ある程度のカスタマイズが可能複雑
カスタムアイコンエンジン高度なカスタマイズが可能複雑
  • Qt 6 以降では、QIcon::fromTheme() 関数で QIcon::ThemeIconMode::PreferHighRes モードを指定することで、高解像度のピクセルマップを取得することができます。
  • Qt 5.15 以降では、QIcon::setThemeIcon() 関数で QIcon::ThemeMode::PreferHighRes モードを指定することで、高解像度のピクセルマップを取得することができます。