【保存版】Qt: QGuiApplication::screenRemoved() の完全ガイド


QGuiApplication::screenRemoved() は、Qt GUI アプリケーションにおいて、接続されたディスプレイデバイスが取り外された際に通知されるシグナルです。このシグナルは、アプリケーションがディスプレイの変更に適応し、ユーザーインターフェースを更新するために使用されます。

シグナルの引数

QGuiApplication::screenRemoved() シグナルは、以下の引数を持つスロットに渡されます。

  • screen: 取り外されたディスプレイデバイスを表す QScreen オブジェクト

シグナルの接続

QGuiApplication::screenRemoved() シグナルは、connect() 関数を使用してスロットに接続できます。以下の例は、シグナルを myScreenRemoved() スロットに接続する方法を示しています。

connect(QGuiApplication::instance(), &QGuiApplication::screenRemoved, this, &MyClass::myScreenRemoved);

シグナルの処理

myScreenRemoved() スロットは、取り外されたディスプレイデバイスに関する情報を処理するために使用されます。このスロット内で、以下の操作を実行できます。

  • ユーザーにディスプレイの取り外しを通知する
  • アプリケーションのレイアウトを更新する
  • 取り外されたディスプレイに表示されていたウィジェットを非表示にする

以下の例は、QGuiApplication::screenRemoved() シグナルを使用して、取り外されたディスプレイに表示されていたウィジェットを非表示にする方法を示しています。

void MyClass::myScreenRemoved(QScreen *screen)
{
    // 取り外されたディスプレイに表示されていたウィジェットを非表示にする
    for (QWidget *widget : screen->widgets()) {
        widget->hide();
    }
}
  • シグナルが発行される前に、取り外されたディスプレイに表示されていたウィジェットは、QCoreApplication::instance()aboutToQuit() シグナルに接続されたスロットからアクセスできます。
  • QGuiApplication::screenRemoved() シグナルは、メインスレッドでのみ発行されます。


#include <QApplication>
#include <QScreen>
#include <QWidget>

class MyClass : public QObject
{
public:
    MyClass()
    {
        connect(QGuiApplication::instance(), &QGuiApplication::screenRemoved, this, &MyClass::myScreenRemoved);
    }

private:
    void myScreenRemoved(QScreen *screen)
    {
        // 取り外されたディスプレイに表示されていたウィジェットを非表示にする
        for (QWidget *widget : screen->widgets()) {
            widget->hide();
        }
    }
};

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

    // ウィジェットを作成して表示する
    QWidget widget;
    widget.show();

    MyClass myClass;

    return app.exec();
}

このコードの説明

  1. #include ディレクティブを使用して、必要なヘッダーファイルをインクルードします。
  2. MyClass クラスを定義します。このクラスは、QGuiApplication::screenRemoved() シグナルに接続するためのスロット myScreenRemoved() を持つ QObject を継承します。
  3. main() 関数内で、QApplication オブジェクトを作成し、ウィジェットを作成して表示します。
  4. MyClass オブジェクトを作成し、QGuiApplication::screenRemoved() シグナルに myScreenRemoved() スロットを接続します。
  5. アプリケーションを実行します。
  1. アプリケーションウィンドウが表示されます。
  2. ディスプレイデバイスを接続します。
  3. アプリケーションウィンドウが新しいディスプレイデバイスに表示されます。
  4. ディスプレイデバイスを取り外します。
  5. アプリケーションウィンドウが元のディスプレイデバイスにのみ表示されます。
  • コードを実行するには、Qt Creator などの IDE を使用する必要があります。
  • このコードは、Qt 6.x でコンパイルして実行することを想定しています。


QGuiApplication::screenRemoved() の制限

  • シグナルが発行される前に、ウィジェットが破棄されている可能性があります。
  • 取り外されたディスプレイに表示されていたウィジェットにのみアクセスできます。
  • メインスレッドでのみ発行されるため、スレッドセーフではありません。

これらの制限を回避するために、QGuiApplication::screenRemoved() の代替方法をいくつか検討する必要があります。

代替方法

  1. QMetaObject::connectSignalsByName()` を使用する
class MyClass : public QObject
{
public:
    MyClass()
    {
        QScreen *screen = QGuiApplication::primaryScreen();
        connect(screen, &QScreen::screenRemoved, this, &MyClass::myScreenRemoved);
    }

private:
    void myScreenRemoved()
    {
        // 取り外されたディスプレイに関する処理を行う
    }
};
  1. QWindowSystem::handleScreenRemoved()` を使用する

QWindowSystem クラスの handleScreenRemoved() メソッドを使用して、ディスプレイの取り外しを処理できます。この方法は、スレッドセーフであり、取り外されたディスプレイに表示されていたすべてのウィジェットにアクセスできます。

class MyClass : public QObject
{
public:
    MyClass()
    {
        QWindowSystem::instance()->connectScreenRemoved(this, &MyClass::myScreenRemoved);
    }

private:
    void myScreenRemoved(int screenId)
    {
        // 取り外されたディスプレイに関する処理を行う
    }
};
  1. 独自のシグナルとスロットを使用する

独自のシグナルとスロットを使用して、ディスプレイの取り外しを通知できます。この方法は、より柔軟な制御を提供しますが、より多くのコードを記述する必要があります。

class MyClass : public QObject
{
public:
    MyClass()
    {
        connect(this, &MyClass::screenRemoved, this, &MyClass::myScreenRemoved);
    }

signals:
    void screenRemoved(int screenId);

private:
    void myScreenRemoved(int screenId)
    {
        // 取り外されたディスプレイに関する処理を行う
    }
};

どの代替方法を選択するべきか

どの代替方法を選択するかは、アプリケーションの要件によって異なります。

  • 取り外されたディスプレイに表示されていたすべてのウィジェットにアクセスする必要がある場合は、QWindowSystem::handleScreenRemoved() または独自のシグナルとスロットを使用する必要があります。
  • スレッドセーフな方法でディスプレイの取り外しを処理する必要がある場合は、QMetaObject::connectSignalsByName() または QWindowSystem::handleScreenRemoved() を使用する必要があります。
  • メインスレッドでのみディスプレイの取り外しを処理する必要がある場合は、QGuiApplication::screenRemoved() を使用するのが最も簡単です。
  • アプリケーションが X11 または Wayland を使用する場合は、QWindowSystem::handleScreenRemoved() メソッドを使用する必要があります。
  • アプリケーションが複数のディスプレイデバイスをサポートする場合は、すべてのディスプレイデバイスの screenRemoved() シグナルに接続する必要があります。