【Qtプログラミング】QWidget::stackUnder()実践コード例で学ぶZオーダー制御

2025-05-27

QWidget::stackUnder() は Qt プログラミングにおけるウィジェットのスタック順序(重なり順)を操作するための関数です。簡単に言うと、あるウィジェットを別の特定のウィジェットの下に配置する際に使用します。

以下に詳しく説明します。

stackUnder(QWidget* w) 関数は、呼び出し元のウィジェット(例えば this)を、引数として渡されたウィジェット wすぐ下に配置します。これは、同じ親を持つウィジェット間で重なり順序を変更したい場合に特に役立ちます。

なぜ stackUnder() が必要か?

Qt のウィジェットは、デフォルトで作成された順序、または親ウィジェットに追加された順序で重なります。後から作成されたウィジェットは、通常、以前に作成されたウィジェットの上に表示されます。しかし、特定のウィジェットを他のウィジェットの下に固定したい場合や、動的に重なり順序を変更したい場合があります。

例えば、

  • 複雑なレイアウト
    複数のウィジェットが重なり合って表示されるようなカスタムレイアウトを実装する際に、特定のウィジェットの表示順序を制御したい場合。
  • オーバーレイ
    オーバーレイとして表示されるウィジェット(例: ポップアップ、ツールチップ)が、特定の基本ウィジェットの上ではなく下に表示されるようにしたい場合。
  • 背景ウィジェット
    特定のウィジェットを常に他のすべてのウィジェットの背景として表示したい場合。

このような場合に stackUnder() が役立ちます。

使用例

#include <QtWidgets>

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

    QWidget window;
    window.resize(400, 300);

    QPushButton *button1 = new QPushButton("Button 1", &window);
    button1->setGeometry(50, 50, 100, 50);

    QPushButton *button2 = new QPushButton("Button 2", &window);
    button2->setGeometry(80, 80, 100, 50); // Button 2 が Button 1 の上に重なる

    // ここで stackUnder() を使用
    // button2 を button1 の下に配置する
    button2->stackUnder(button1); // これにより、button2 は button1 の下になる

    window.show();

    return app.exec();
}

上記の例では、button2 は通常、button1 の上に重なって表示されます。しかし、button2->stackUnder(button1); を呼び出すことで、button2button1下に配置され、button1button2 の上に表示されるようになります。

  • 他のスタック順序関数
    Qt には他にも raise()(最前面に移動)や lower()(最背面に移動)といったスタック順序を操作する関数がありますが、stackUnder() は「特定のウィジェットの下に置く」というより具体的な操作を提供します。
  • レイアウトとの関係
    QLayout を使用してウィジェットを配置している場合、レイアウトがウィジェットのジオメトリと重なり順序を管理するため、stackUnder() の効果はレイアウトの動作によって上書きされる可能性があります。stackUnder() は、setGeometry() などで手動で位置とサイズを設定する、あるいはカスタムペイントを行うような場合に特に有効です。
  • 同じ親を持つウィジェット
    stackUnder() は、呼び出し元のウィジェットと引数として渡されたウィジェットが同じ親を持つ場合にのみ意味があります。異なる親を持つウィジェットに対して stackUnder() を呼び出しても、期待通りの効果は得られません。


stackUnder() を呼び出してもウィジェットの順序が変わらない

よくある原因

  • 可視性の問題
    ウィジェットがそもそも表示されていない場合(hide() されている、または親が非表示になっているなど)、stackUnder() を呼び出しても視覚的な変化はわかりません。
  • ウィジェットがトップレベルウィンドウである
    ウィジェットが Qt::Window フラグを持つトップレベルウィンドウである場合、親を持たないため、stackUnder() は他のトップレベルウィンドウとの関係でのみ機能します。通常、他のウィンドウの下に隠れることは期待通りに機能しないことがあります。
  • レイアウトの使用
    最も一般的な落とし穴の一つです。Qt のレイアウト(QHBoxLayout, QVBoxLayout, QGridLayout など)を使用している場合、レイアウトがウィジェットのサイズ、位置、そして重なり順序を厳密に管理します。stackUnder() を呼び出しても、レイアウトによってすぐに元の順序に戻されてしまうか、全く効果がない場合があります。

    • QVBoxLayout に追加された2つのボタンがある場合、stackUnder() を使用しても、レイアウトがそれらを垂直に並べるため、重なり順序の変更はできません。
  • 異なる親を持つウィジェット
    stackUnder() は、同じ親を持つ兄弟ウィジェット間でしか機能しません。異なる親を持つウィジェットに対して呼び出しても、効果はありません。

    • 親が異なる widgetAwidgetB がある場合、widgetA->stackUnder(widgetB) は何も影響を与えません。

トラブルシューティング

  • 可視性を確認する
    widget->isVisible()true を返すことを確認し、親ウィジェットも表示されていることを確認してください。
  • カスタムペイント
    ウィジェットの重なり順序をプログラムで完全に制御したい場合は、親ウィジェットの paintEvent() をオーバーライドし、QPainter を使って子ウィジェットを手動で描画することも検討できます。これはより複雑なアプローチですが、完全な柔軟性を提供します。
  • レイアウトを使用しない
    stackUnder() の効果を最大限に活用したい場合は、手動でウィジェットのジオメトリ(位置とサイズ)を設定する必要があります(例: widget->setGeometry(x, y, w, h);)。レイアウトは強力ですが、ウィジェットの重なり順序を手動で制御したい場合には適していません。
  • 親を確認する
    widgetA->parent()widgetB->parent() が同じポインタを返すことを確認してください。もし異なる場合は、stackUnder() は機能しません。ウィジェットを同じ親の下に再配置するか、別の方法を検討する必要があります。

ウィジェットの一部が切り取られて表示される

よくある原因

  • 親ウィジェットのクリッピング
    親ウィジェットが子ウィジェットの領域をクリップするように設定されている場合(setContentsMargins() などでマージンが設定されている場合や、固定サイズになっている場合)、子が親の境界を超えて描画されると切り取られます。
  • ジオメトリの衝突
    stackUnder() はウィジェットの重なり順序を変更しますが、そのサイズや位置は変更しません。もしウィジェットが重なり合っていて、stackUnder() で下になったウィジェットが、上のウィジェットによって完全に覆い隠されてしまう場合、切り取られて見えないことがあります。

トラブルシューティング

  • repaint() または update() の呼び出し
    変更がすぐに反映されない場合は、関連するウィジェットまたは親ウィジェットに対して repaint() または update() を呼び出すことで、強制的に再描画を促すことができます。
  • ジオメトリの調整
    stackUnder() で順序を変更した後、必要に応じてウィジェットのサイズや位置を調整し、適切に表示されるようにしてください。

ウィジェットの背景が透過しない

よくある原因

  • 適切なフラグがない
    透過したいウィジェットが Qt::WA_TranslucentBackground 属性や Qt::WA_NoSystemBackground 属性を正しく設定していない場合。
  • autoFillBackground が true
    ウィジェットの autoFillBackground プロパティが true に設定されている場合、Qt はウィジェットの背景をパレットの Window ロールで塗りつぶします。これにより、下のウィジェットが透けて見えなくなります。

トラブルシューティング

  • カスタムペイントで透過を描画
    paintEvent()QPainter を使用してウィジェットを描画する場合、背景を透明にするために QPainter::setCompositionMode(QPainter::CompositionMode_Clear); などを使用することができます。
  • 適切なウィジェット属性の設定
    widget->setAttribute(Qt::WA_TranslucentBackground);widget->setAttribute(Qt::WA_NoSystemBackground); を設定します。
  • autoFillBackground を false に設定
    透過させたいウィジェットに対して widget->setAutoFillBackground(false); を呼び出します。

ウィジェットがちらつく

よくある原因

  • 頻繁な再描画
    stackUnder() や関連するジオメトリ変更、可視性変更などが頻繁に発生すると、ウィジェットの再描画が繰り返され、ちらつきが発生することがあります。
  • ダブルバッファリング
    ウィジェットが複雑な描画を行う場合、ダブルバッファリングを有効にすることでちらつきを軽減できます。ただし、Qt の多くのウィジェットはデフォルトでダブルバッファリングを使用しているため、この問題はあまり一般的ではありません。
  • update() と repaint() の使い分け
    update() はイベントループに再描画イベントを追加し、可能な限り最適化されたタイミングで再描画されます。repaint() は即座に再描画を強制します。通常は update() の方がパフォーマンスに優れており、ちらつきを抑えるのに役立ちます。
  • デバッグ出力
    qDebug() を使用して、ウィジェットの親、ジオメトリ、可視性などのプロパティをコンソールに出力し、期待通りの値になっているか確認します。
  • Qt ドキュメントの参照
    QWidget::stackUnder() のドキュメントを再確認し、その制約と使用方法を理解することが重要です。
  • ミニマムな再現コードの作成
    問題が発生した場合、問題の核心となる部分だけを抜き出して、できるだけシンプルなコードで再現することを試みてください。これにより、原因を特定しやすくなります。


Qtにおける QWidget::stackUnder() のプログラミング例をいくつかご紹介します。この関数は、同じ親を持つウィジェット間で、あるウィジェットを別の特定のウィジェットのすぐ下に配置するために使われます。

例1: 2つのボタンの重なり順序を変更する基本的な例

この例では、2つのボタンを作成し、stackUnder() を使って重なり順序を動的に変更する方法を示します。

#include <QtWidgets>

class MyWindow : public QWidget
{
    Q_OBJECT

public:
    MyWindow(QWidget *parent = nullptr) : QWidget(parent)
    {
        // ウィンドウのサイズを設定
        resize(400, 300);
        setWindowTitle("stackUnder() の基本例");

        // ボタン1を作成
        button1 = new QPushButton("Button 1 (上)", this);
        button1->setGeometry(50, 50, 150, 80); // 位置とサイズを設定
        button1->setStyleSheet("background-color: lightblue;"); // 見やすくするために色を付ける

        // ボタン2を作成
        button2 = new QPushButton("Button 2 (下)", this);
        button2->setGeometry(80, 80, 150, 80); // button1と重なるように位置を設定
        button2->setStyleSheet("background-color: lightcoral;"); // 見やすくするために色を付ける

        // 初期状態では、button2がbutton1の上に重なる(後から作成されたため)

        // 順序を入れ替えるためのボタン
        QPushButton *swapButton = new QPushButton("順序を入れ替える", this);
        swapButton->setGeometry(250, 150, 120, 40);

        // ボタンがクリックされたら順序を入れ替えるスロットを接続
        connect(swapButton, &QPushButton::clicked, this, &MyWindow::swapOrder);
    }

private slots:
    void swapOrder()
    {
        // 現在、button2がbutton1の下にあるか確認(初期状態を逆転させる)
        // stackUnder(button1) は button2 を button1 の下に置く
        // button1->stackUnder(button2) は button1 を button2 の下に置く
        static bool isButton2UnderButton1 = false; // 初期状態ではbutton2が上にいると仮定

        if (!isButton2UnderButton1) {
            // button2をbutton1の下に配置
            button2->stackUnder(button1);
            button2->setText("Button 2 (下)");
            button1->setText("Button 1 (上)");
            qDebug() << "Button 2 を Button 1 の下に配置しました。";
        } else {
            // button1をbutton2の下に配置(つまり、button2がbutton1の上にくる)
            button1->stackUnder(button2);
            button1->setText("Button 1 (下)");
            button2->setText("Button 2 (上)");
            qDebug() << "Button 1 を Button 2 の下に配置しました。";
        }
        isButton2UnderButton1 = !isButton2UnderButton1; // 状態を反転
    }

private:
    QPushButton *button1;
    QPushButton *button2;
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MyWindow window;
    window.show();
    return app.exec();
}

#include "main.moc" // mocファイルをインクルードすることを忘れないでください

解説

  1. MyWindow クラスは QWidget を継承し、2つの QPushButton をメンバーとして持っています。
  2. コンストラクタで2つのボタンを親ウィジェット(MyWindow)に配置します。setGeometry() を使って、これらが重なるように意図的に位置を設定しています。
  3. 初期状態では、button2button1 の上に重なります。これは、button2button1 の後に作成されたためです。
  4. "順序を入れ替える" ボタンがクリックされると、swapOrder() スロットが呼び出されます。
  5. swapOrder() スロットでは、button2->stackUnder(button1); を呼び出すことで、button2button1 の下に配置します。これにより、button1button2 の上に表示されるようになります。
  6. 2回目以降のクリックでは、button1->stackUnder(button2); を呼び出し、順序を元に戻しています。
  7. setStyleSheet で背景色を付けているため、重なり順序の変化が視覚的にわかりやすくなっています。

この例では、背景として機能するカスタムウィジェットを作成し、その上に別のウィジェットを配置する際に stackUnder() を使用します。背景ウィジェットは常に他のウィジェットの下に表示されるようにします。

#include <QtWidgets>
#include <QPainter>

// カスタム背景ウィジェット
class BackgroundWidget : public QWidget
{
    Q_OBJECT
public:
    BackgroundWidget(QColor color, QWidget *parent = nullptr)
        : QWidget(parent), m_color(color)
    {
        // 背景を自動で塗りつぶさないように設定
        // これにより、親ウィジェットの背景や、下のウィジェットの描画が見えるようになる
        setAttribute(Qt::WA_NoSystemBackground);
        setAttribute(Qt::WA_TranslucentBackground);
        setAutoFillBackground(false); // これも重要
    }

protected:
    void paintEvent(QPaintEvent *event) override
    {
        Q_UNUSED(event);
        QPainter painter(this);
        painter.fillRect(rect(), m_color); // 指定された色で背景を塗りつぶす
        // 他の描画が必要であればここに追加
    }

private:
    QColor m_color;
};

class MyComplexWindow : public QWidget
{
    Q_OBJECT

public:
    MyComplexWindow(QWidget *parent = nullptr) : QWidget(parent)
    {
        resize(500, 400);
        setWindowTitle("背景ウィジェットの例");

        // 1. 背景ウィジェットを作成
        backgroundWidget = new BackgroundWidget(QColor(220, 255, 220), this); // 親はMyComplexWindow
        backgroundWidget->setGeometry(0, 0, width(), height()); // ウィンドウ全体を覆うように設定
        backgroundWidget->setObjectName("backgroundWidget"); // デバッグ用にオブジェクト名を設定

        // 2. その他のウィジェットを作成
        QLabel *label = new QLabel("このラベルは背景の上にあります。", this);
        label->setGeometry(50, 50, 300, 50);
        label->setStyleSheet("background-color: rgba(255, 255, 255, 180); font-size: 16px; padding: 5px;");

        QPushButton *button = new QPushButton("操作ボタン", this);
        button->setGeometry(50, 120, 150, 40);

        // 3. backgroundWidgetを他のウィジェットの下に配置
        // QLabelとQPushButtonはbackgroundWidgetの後に作成されたため、デフォルトでは上に重なる
        // backgroundWidgetが常に背景となるようにstackUnder()を使用
        // 注意: ここでstackUnder()を呼ぶと、backgroundWidgetが他のウィジェットの下に移動する。
        //       しかし、他のウィジェットの描画順序は変わらないため、
        //       通常はbackgroundWidgetを一番下にしたいのであれば、
        //       backgroundWidgetの後に他のウィジェットを作成するだけで十分。
        //       ただし、動的に重なり順序を変更したい場合は有効。
        //
        //       ここでは、動的な配置の例として、ボタンとラベルを作成後に
        //       背景を下に持ってくることを示す。
        backgroundWidget->stackUnder(label); // ラベルの下に配置(結果的にボタンの下にもなる)

        // ウィンドウのリサイズイベントを捕捉して背景ウィジェットのサイズを更新
        // (レイアウトを使用しない場合、手動でサイズ変更に対応する必要がある)
        connect(this, &MyComplexWindow::resized, this, &MyComplexWindow::onWindowResized);
    }

protected:
    void resizeEvent(QResizeEvent *event) override
    {
        QWidget::resizeEvent(event);
        // 背景ウィジェットのサイズを親ウィジェットに合わせて更新
        if (backgroundWidget) {
            backgroundWidget->setGeometry(0, 0, width(), height());
            emit resized(); // スロットに接続するためにシグナルを発行
        }
    }

signals:
    void resized(); // resizeEvent からスロットを呼び出すためのカスタムシグナル

private:
    BackgroundWidget *backgroundWidget;
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MyComplexWindow window;
    window.show();
    return app.exec();
}

#include "main.moc" // mocファイルをインクルードすることを忘れないでください
  1. BackgroundWidget クラス
    • QWidget を継承し、コンストラクタで背景色を受け取ります。
    • setAttribute(Qt::WA_NoSystemBackground);setAutoFillBackground(false); を設定しています。これは、ウィジェットがシステムによって自動的に背景を塗りつぶすのを防ぎ、透明な背景や下のウィジェットが見えるようにするために重要です。
    • paintEvent() をオーバーライドし、QPainter を使って指定された色でウィジェット全体を塗りつぶします。
  2. MyComplexWindow クラス
    • BackgroundWidget のインスタンスをまず作成し、ウィンドウ全体を覆うように setGeometry() で配置します。
    • 次に、QLabelQPushButton を作成し、それらも MyComplexWindow を親として配置します。
    • 重要な部分
      backgroundWidget->stackUnder(label); を呼び出します。これにより、backgroundWidgetlabel の下に配置されます。QLabelQPushButton よりも先に作成されているので、backgroundWidget は事実上、他のすべてのウィジェットの下に置かれることになります。
    • resizeEvent をオーバーライドし、ウィンドウサイズが変更されたときに backgroundWidget のサイズも変更されるようにしています。レイアウトを使用しない場合、このように手動で子ウィジェットのジオメトリを管理する必要があります。


QWidget::raise() と QWidget::lower()

これらは stackUnder() と同様にウィジェットの Zオーダーを操作しますが、より単純な「最前面に移動」と「最背面に移動」を提供します。

  • widget->lower(): 指定されたウィジェットを、その兄弟ウィジェットの中で最背面(最も低いZオーダー)に移動します。
  • widget->raise(): 指定されたウィジェットを、その兄弟ウィジェットの中で最前面(最も高いZオーダー)に移動します。

使用シナリオ

  • 常に背景として機能させたいウィジェット(ただし、後述のレイアウトの方が優れている場合が多い)。
  • ポップアップやモーダルダイアログなど、一時的に最前面に表示したいウィジェット。


#include <QtWidgets>

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

    QWidget window;
    window.resize(400, 300);

    QPushButton *button1 = new QPushButton("Button 1", &window);
    button1->setGeometry(50, 50, 100, 50);
    button1->setStyleSheet("background-color: lightblue;");

    QPushButton *button2 = new QPushButton("Button 2", &window);
    button2->setGeometry(80, 80, 100, 50);
    button2->setStyleSheet("background-color: lightcoral;");

    // button2 を button1 の上に配置(デフォルト)

    // button2 を最背面に移動
    button2->lower(); // button1 の下になる

    QPushButton *raiseButton = new QPushButton("Button 1 を最前面へ", &window);
    raiseButton->setGeometry(200, 150, 150, 40);
    QObject::connect(raiseButton, &QPushButton::clicked, [&]() {
        button1->raise(); // button1 を最前面に移動
    });

    QPushButton *lowerButton = new QPushButton("Button 2 を最背面へ", &window);
    lowerButton->setGeometry(200, 200, 150, 40);
    QObject::connect(lowerButton, &QPushButton::clicked, [&]() {
        button2->lower(); // button2 を最背面に移動
    });

    window.show();
    return app.exec();
}

Qt レイアウトシステム

ほとんどの Qt アプリケーションでは、ウィジェットの配置とサイズ変更にはレイアウトを使用することが推奨されます。レイアウトはウィジェットの Zオーダーを直接制御するものではありませんが、Zオーダーが必要な状況を減らすことができます。なぜなら、レイアウトはウィジェットが重なり合わないように配置することを目的としているからです。

しかし、特定の状況では、レイアウト内で Zオーダーを制御する必要があるかもしれません。その場合、通常はウィジェットの作成順序が Zオーダーに影響します。レイアウトに追加されたウィジェットは、追加された順に Zオーダーが決定される傾向があります(後に追加されたものが上にくる)。

使用シナリオ

  • 異なる画面サイズや解像度に対応する、レスポンシブなUI。
  • 標準的なUIレイアウト(垂直、水平、グリッドなど)。

制限

  • レイアウトを使用している場合、stackUnder()raise()lower() はレイアウトの管理下にあり、期待通りに機能しないか、レイアウトによってすぐに元に戻される可能性があります。

QStackedWidget

QStackedWidget は、複数のウィジェットを重ねて表示し、一度に1つのウィジェットのみを表示する特殊なレイアウトウィジェットです。タブ付きインターフェースやウィザードのようなUIを作成するのに最適です。

  • setCurrentWidget(QWidget *widget): 指定したウィジェットを表示します。
  • setCurrentIndex(int index): 指定したインデックスのウィジェットを表示します。
  • addWidget(QWidget *widget): ウィジェットを追加します。

使用シナリオ

  • 完全に重なるウィジェット群から、一つを選択して表示したい場合。
  • ウィザード形式のUI。
  • 複数のビューを切り替える必要がある場合(例: 設定画面の各セクション)。


#include <QtWidgets>

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

    QWidget window;
    window.resize(400, 300);
    QVBoxLayout *mainLayout = new QVBoxLayout(&window);

    QStackedWidget *stackedWidget = new QStackedWidget(&window);

    // ページ1
    QWidget *page1 = new QWidget();
    QVBoxLayout *page1Layout = new QVBoxLayout(page1);
    page1Layout->addWidget(new QLabel("これはページ1です。"));
    page1Layout->addWidget(new QPushButton("ページ1のボタン"));
    stackedWidget->addWidget(page1);

    // ページ2
    QWidget *page2 = new QWidget();
    QVBoxLayout *page2Layout = new QVBoxLayout(page2);
    page2Layout->addWidget(new QLabel("これはページ2です。異なる内容です。"));
    page2Layout->addWidget(new QPushButton("ページ2の別のボタン"));
    stackedWidget->addWidget(page2);

    mainLayout->addWidget(stackedWidget);

    QPushButton *nextPageButton = new QPushButton("次のページへ", &window);
    mainLayout->addWidget(nextPageButton);

    QObject::connect(nextPageButton, &QPushButton::clicked, [&]() {
        int currentIndex = stackedWidget->currentIndex();
        int nextIndex = (currentIndex + 1) % stackedWidget->count();
        stackedWidget->setCurrentIndex(nextIndex);
    });

    window.show();
    return app.exec();
}

QGraphicsView および QGraphicsScene

より高度なグラフィックスや複雑なアイテムの重なり順序を制御したい場合、QGraphicsView フレームワークが非常に強力な代替手段となります。これは、カスタムな2Dグラフィックスアプリケーション、ダイアグラムエディタ、ゲームなどに適しています。

  • QGraphicsView: シーンを表示するためのウィジェットです。
  • QGraphicsScene: すべての QGraphicsItem を管理し、描画します。
  • QGraphicsItem::setZValue(qreal z): 各アイテムにZ値(浮動小数点数)を設定することで、重なり順序を細かく制御できます。Z値が大きいほど手前に表示されます。

使用シナリオ

  • カスタムな描画ロジックが必要な場合。
  • ドラッグ&ドロップ可能なアイテム、アニメーション。
  • 多数のカスタムグラフィック要素が相互に作用する複雑な2Dシーン。

例 (概念のみ、完全なコードは複雑になるため省略)

// QGraphicsScene と QGraphicsView の設定
QGraphicsScene *scene = new QGraphicsScene();
QGraphicsView *view = new QGraphicsView(scene);

// カスタムアイテムを作成
QGraphicsRectItem *rect1 = new QGraphicsRectItem(0, 0, 100, 100);
rect1->setBrush(Qt::blue);
rect1->setPos(50, 50);
scene->addItem(rect1);

QGraphicsEllipseItem *ellipse1 = new QGraphicsEllipseItem(0, 0, 80, 80);
ellipse1->setBrush(Qt::red);
ellipse1->setPos(80, 80);
scene->addItem(ellipse1);

// Z値を設定して重なり順序を制御
rect1->setZValue(1.0);     // 楕円の上に表示される
ellipse1->setZValue(0.5); // 四角の下に表示される

// または、後から追加されたアイテムが上にくる
// ellipse1->setZValue(1.5); // 四角の上に表示される

これは最も低レベルな方法であり、最も柔軟性があります。親ウィジェットの paintEvent() をオーバーライドし、その中で子ウィジェットを好きな順序で手動で描画します。これは通常、子ウィジェットが透過している場合や、特定の描画効果を適用したい場合にのみ検討されます。

使用シナリオ

  • 特定の合成モード(QPainter::CompositionMode)を使用して、ウィジェットの描画を組み合わせる場合。
  • 子ウィジェットの描画を親ウィジェットの描画と統合したい場合。
  • 完全にカスタムな描画が必要な場合。
  • 子ウィジェットが標準的な Qt ウィジェットの機能(イベント処理など)を維持したい場合、このアプローチは非常に複雑になる可能性があります。通常は、カスタムな視覚要素を描画するために使用されます。
  • 究極の描画制御
    親ウィジェットの paintEvent() でのカスタム描画
  • 複雑なグラフィックシーン
    QGraphicsView フレームワーク
  • 複数ページの切り替え
    QStackedWidget
  • 一般的なUI配置
    Qt レイアウトシステム (通常 Zオーダーの直接制御は不要)
  • 特定のウィジェットの下に置く
    stackUnder() (手動ジオメトリ設定時)
  • 単純な最前面/最背面
    raise()lower()