Qt GUIにおけるオフスクリーンサーフェス画面変更検知:QOffscreenSurface::screenChanged()徹底解説


QOffscreenSurface::screenChanged() は、Qt GUIにおけるオフスクリーンサーフェスオブジェクトの画面が変更された際にシグナルを発行する関数です。これは、オフスクリーンサーフェスが明示的に setScreen() で設定された場合、またはウィンドウの画面が削除された際に自動的に発生します。

機能

このシグナルは、以下の状況で発行されます。

  • ウィンドウの画面が削除された場合
  • setScreen() を使用してオフスクリーンサーフェスに新しい画面が設定された場合

シグナルが発行されると、QScreen* ポインタを引数として渡されたスロットが呼び出されます。このポインタは、オフスクリーンサーフェスに関連付けられた現在の画面を表します。

QOffscreenSurface surface;

// 画面を設定します。
surface.setScreen(QGuiApplication::primaryScreen());

// 画面変更シグナルに接続します。
connect(&surface, &QOffscreenSurface::screenChanged, this, &MyClass::onScreenChanged);

void MyClass::onScreenChanged(QScreen* screen)
{
    // 新しい画面に関する処理を実行します。
    qDebug() << "画面が変更されました: " << screen->name();
}
  • screenChanged() シグナルは、メインスレッドでのみ発行されます。
  • オフスクリーンサーフェスが作成されている場合、新しい画面に再作成されます。


QOffscreenSurface surface;

// 画面を設定します。
surface.setScreen(QGuiApplication::primaryScreen());

// 画面変更シグナルに接続します。
connect(&surface, &QOffscreenSurface::screenChanged, this, &MyClass::onScreenChanged);

void MyClass::onScreenChanged(QScreen* screen)
{
    // 新しい画面のサイズを取得します。
    QSize newSize = screen->size();

    // オフスクリーンサーフェスのサイズを更新します。
    surface.setSize(newSize);
}

例 2: 画面変更時にオフスクリーンサーフェスの内容を再描画する

QOffscreenSurface surface;
QPainter painter;

// 画面を設定します。
surface.setScreen(QGuiApplication::primaryScreen());

// 画面変更シグナルに接続します。
connect(&surface, &QOffscreenSurface::screenChanged, this, &MyClass::onScreenChanged);

void MyClass::onScreenChanged(QScreen* screen)
{
    // オフスクリーンサーフェスのペインターを取得します。
    painter.begin(&surface);

    // 画面に描画します。
    painter.fillRect(surface.rect(), Qt::red);

    // 描画を終了します。
    painter.end();
}

これらの例はあくまでも基本的なものです。実際のアプリケーションでは、より複雑な処理が必要になる場合があります。



代替方法

QWindow::screenChanged() シグナルを使用する

QWindow::screenChanged() シグナルは、ウィンドウの画面が変更された際に発行されます。オフスクリーンサーフェスがウィンドウ内に埋め込まれている場合は、このシグナルを使用して画面変更を検知できます。

QOffscreenSurface surface;
QWidget widget;

// オフスクリーンサーフェスをウィジェットに埋め込みます。
widget.setSurface(&surface);

// 画面変更シグナルに接続します。
connect(&widget, &QWidget::screenChanged, this, &MyClass::onScreenChanged);

void MyClass::onScreenChanged(QScreen* screen)
{
    // 新しい画面に関する処理を実行します。
    qDebug() << "画面が変更されました: " << screen->name();
}

QScreen::availableGeometryChanged() シグナルを使用する

QScreen::availableGeometryChanged() シグナルは、画面の利用可能な領域が変更された際に発行されます。オフスクリーンサーフェスのサイズが画面の利用可能な領域に依存している場合は、このシグナルを使用して画面変更を検知できます。

QOffscreenSurface surface;
QScreen* screen = QGuiApplication::primaryScreen();

// 画面変更シグナルに接続します。
connect(screen, &QScreen::availableGeometryChanged, this, &MyClass::onScreenChanged);

void MyClass::onScreenChanged()
{
    // 新しい画面の利用可能な領域を取得します。
    QRect availableGeometry = screen->availableGeometry();

    // オフスクリーンサーフェスのサイズを更新します。
    surface.setSize(availableGeometry.size());
}

タイマーを使用して定期的に画面をチェックする

タイマーを使用して定期的に画面をチェックすることで、画面変更を検知することもできます。ただし、この方法は CPU 負荷が高くなる可能性があるため、頻繁な画面変更が予想される場合にのみ使用することをお勧めします。

QOffscreenSurface surface;
QTimer timer;

// 画面チェックタイマーを設定します。
timer.setInterval(1000); // 1秒ごとにチェック

// タイマーシグナルに接続します。
connect(&timer, &QTimer::timeout, this, &MyClass::checkScreen);

// オフスクリーンサーフェスが作成されている場合、タイマーを開始します。
if (surface.isCreated()) {
    timer.start();
}

void MyClass::checkScreen()
{
    QScreen* currentScreen = QGuiApplication::primaryScreen();

    // 現在の画面と前回の画面を比較します。
    if (currentScreen != previousScreen) {
        // 画面が変更されました。
        previousScreen = currentScreen;

        // 新しい画面に関する処理を実行します。
        qDebug() << "画面が変更されました: " << currentScreen->name();
    }
}

最適な方法の選択

最適な方法は、アプリケーションの要件によって異なります。画面変更を頻繁に検知する必要がある場合は、QOffscreenSurface::screenChanged() 関数を使用するのが最善です。画面変更をそれほど頻繁に検知する必要がない場合は、QWindow::screenChanged() シグナルや QScreen::availableGeometryChanged() シグナルを使用することを検討してください。タイマーを使用して画面をチェックする方法は、CPU 負荷が高くなる可能性があるため、最後の手段としてのみ使用する必要があります。

  • QOffscreenSurface::screenChanged() シグナルは、メインスレッドでのみ発行されます。
  • オフスクリーンサーフェスが複数の画面にまたがる場合は、QOffscreenSurface::screenChanged() シグナルが各画面変更に対して個別に発行されます。