QAbstractScrollArea::cornerWidget()

2025-05-26

QAbstractScrollAreaは、スクロール可能な領域を提供するQtウィジェットの抽象基底クラスです。これには、表示領域(ビューポート)、垂直スクロールバー、水平スクロールバーが含まれます。QScrollAreaはこのQAbstractScrollAreaを継承しており、より一般的なスクロール領域として利用されます。

cornerWidget()とは?

QAbstractScrollArea::cornerWidget()メソッドは、垂直スクロールバーと水平スクロールバーが交差する隅の部分(通常は右下隅)に表示されるウィジェットを返します。

デフォルトでは、この隅には何もウィジェットがありません。しかし、setCornerWidget()メソッドを使って、ここに任意のQWidgetを設定することができます。

なぜcornerWidgetが必要なのか?

この隅のスペースは、スクロールバーが表示される際に自動的に確保されます。ここにカスタムウィジェットを配置することで、以下のような用途に利用できます。

  • 装飾
    単純にデザイン上のアクセントとして利用する。
  • 追加機能のボタン
    スクロール領域全体の機能(例:リセットボタン、拡大/縮小ボタンなど)を配置する。
  • 情報表示
    スクロール領域の状態に関する短い情報を表示する。

例えば、QScrollAreaの右下隅にボタンを配置したい場合、次のようにします。

#include <QApplication>
#include <QScrollArea>
#include <QPushButton>
#include <QVBoxLayout>

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

    // スクロールエリアを作成
    QScrollArea *scrollArea = new QScrollArea();
    scrollArea->setWindowTitle("Corner Widget Example");

    // スクロールするコンテンツとなるウィジェットを作成
    QWidget *contentWidget = new QWidget();
    QVBoxLayout *contentLayout = new QVBoxLayout(contentWidget);

    for (int i = 0; i < 50; ++i) {
        contentLayout->addWidget(new QPushButton(QString("Button %1").arg(i + 1)));
    }
    contentWidget->setLayout(contentLayout);

    // コンテンツウィジェットをスクロールエリアに設定
    scrollArea->setWidget(contentWidget);
    scrollArea->setWidgetResizable(true); // コンテンツがスクロールエリアのサイズに合わせてリサイズされるようにする

    // 隅に表示するウィジェット(ボタン)を作成
    QPushButton *cornerButton = new QPushButton("Corner");
    cornerButton->setStyleSheet("background-color: lightblue;"); // 見やすくするためにスタイルを設定

    // 隅ウィジェットを設定
    scrollArea->setCornerWidget(cornerButton);

    scrollArea->resize(300, 400); // ウィンドウサイズを設定
    scrollArea->show();

    return a.exec();
}

このコードを実行すると、スクロールバーが表示された際に、右下のスクロールバーが交差する位置に「Corner」と表示された青いボタンが表示されます。



コーナーウィジェットが表示されない、または期待通りに動作しない

原因

  • ウィジェットのライフサイクル
    setCornerWidget() に渡したウィジェットが、親である QAbstractScrollArea の子になっていない、または何らかの理由で削除されてしまった場合。
  • レイアウトの問題
    QScrollArea の内部構造や、コンテンツウィジェットのレイアウト設定に問題がある場合、スクロールバーの表示が不安定になったり、コーナーウィジェットの配置に影響が出たりすることがあります。特に、setWidgetResizable(true) を設定していない場合、コンテンツウィジェットがスクロールエリアのサイズに正しく適応せず、スクロールバーが表示されないことがあります。
  • コーナーウィジェットが設定されていない
    setCornerWidget() を呼び出していない場合、当然ながら何も表示されません。
  • スクロールバーが表示されていない
    コーナーウィジェットは、垂直スクロールバーと水平スクロールバーの両方が表示される場合にのみ表示されます。スクロールバーが非表示になっている場合(例: Qt::ScrollBarAsNeeded ポリシーで、コンテンツが小さすぎる場合)、コーナーウィジェットは表示されません。

トラブルシューティング

  • cornerWidget() の戻り値を確認する
    qDebug() << scrollArea->cornerWidget(); のようにして、cornerWidget() が実際に設定したウィジェットのポインタを返しているか、または nullptr を返していないかを確認します。
  • setWidgetResizable(true) を確認する
    QScrollArea を使用している場合、scrollArea->setWidgetResizable(true); を呼び出すことで、内部のウィジェット(コンテンツ)がスクロールエリアのサイズ変更に追従し、スクロールバーの表示も適切に行われるようになります。
  • setCornerWidget() を呼び出すことを確認する
    コード内で確実に setCornerWidget() が呼び出されており、有効な QWidget ポインタが渡されていることを確認してください。
  • スクロールバーポリシーを確認する
    デバッグ目的で、一時的に垂直・水平スクロールバーのポリシーを Qt::ScrollBarAlwaysOn に設定し、強制的にスクロールバーを表示させてみてください。これにより、コーナーウィジェットが表示されるかどうかを確認できます。
    scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
    scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
    

コーナーウィジェットのサイズや位置が期待通りにならない

原因

  • スタイルシートの影響
    スタイルシートを使用している場合、予期せぬスタイルが適用されて、コーナーウィジェットの見た目やサイズに影響を与えることがあります。
  • 自動的なサイズ調整
    QAbstractScrollArea は、コーナーウィジェットのサイズをスクロールバーの幅/高さに合わせて自動的に調整します。cornerWidget に設定したウィジェットの sizeHint()minimumSizeHint() が考慮されない場合があります。


基本的なコーナーウィジェットの追加 (QPushButton)

最も基本的な例として、スクロールエリアの右下隅に単純なプッシュボタンを追加します。

#include <QApplication>
#include <QScrollArea>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#include <QDebug> // デバッグ用

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

    // 1. QScrollArea を作成
    QScrollArea *scrollArea = new QScrollArea();
    scrollArea->setWindowTitle("基本コーナーウィジェットの例");
    scrollArea->resize(300, 400); // ウィンドウの初期サイズ

    // 2. スクロールエリアのコンテンツとなるウィジェットを作成
    //    非常に大きなコンテンツを作成し、スクロールバーが表示されるようにします
    QWidget *contentWidget = new QWidget();
    QVBoxLayout *contentLayout = new QVBoxLayout(contentWidget);
    contentLayout->setContentsMargins(10, 10, 10, 10); // マージンを設定

    for (int i = 0; i < 50; ++i) {
        QPushButton *button = new QPushButton(QString("コンテンツボタン %1").arg(i + 1));
        contentLayout->addWidget(button);
    }
    contentWidget->setLayout(contentLayout);

    // 3. コンテンツウィジェットをスクロールエリアに設定
    scrollArea->setWidget(contentWidget);
    // コンテンツウィジェットがスクロールエリアのサイズ変更に追従するようにする
    scrollArea->setWidgetResizable(true);

    // デバッグのため、スクロールバーを常に表示させる (テスト用)
    // scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
    // scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);

    // 4. コーナーウィジェットを作成
    QPushButton *cornerButton = new QPushButton("隅のボタン");
    cornerButton->setStyleSheet("background-color: #A3D900; color: white; border-radius: 5px;"); // 見た目を少し整える

    // 5. コーナーウィジェットをスクロールエリアに設定
    scrollArea->setCornerWidget(cornerButton);

    // 6. コーナーウィジェットが正しく設定されたか確認 (デバッグ)
    qDebug() << "コーナーウィジェットポインタ:" << scrollArea->cornerWidget();
    if (scrollArea->cornerWidget() == cornerButton) {
        qDebug() << "コーナーウィジェットが正常に設定されました。";
    }

    // ウィジェットの表示
    scrollArea->show();

    return a.exec();
}

説明

  • qDebug() を使って、実際にコーナーウィジェットが設定されているかを確認しています。
  • setCornerWidget(cornerButton) で、作成した QPushButton を右下隅に配置しています。
  • setWidgetResizable(true) は非常に重要で、これによりコンテンツがスクロールエリアのサイズに合わせて拡大・縮小し、スクロールバーの表示が適切に行われます。
  • QScrollArea を作成し、その中に大量のボタンを持つ QWidget をコンテンツとして設定しています。これにより、スクロールバーが表示される状態を作り出します。

複数のウィジェットをコーナーに配置する (QLayout を使用)

#include <QApplication>
#include <QScrollArea>
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout> // 水平レイアウト用
#include <QWidget>
#include <QLabel>      // ラベル用

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

    QScrollArea *scrollArea = new QScrollArea();
    scrollArea->setWindowTitle("複数ウィジェットのコーナーの例");
    scrollArea->resize(350, 450);

    // コンテンツウィジェット (省略 - 上記と同じような内容)
    QWidget *contentWidget = new QWidget();
    QVBoxLayout *contentLayout = new QVBoxLayout(contentWidget);
    for (int i = 0; i < 30; ++i) {
        contentLayout->addWidget(new QPushButton(QString("コンテンツアイテム %1").arg(i + 1)));
    }
    contentWidget->setLayout(contentLayout);
    scrollArea->setWidget(contentWidget);
    scrollArea->setWidgetResizable(true);

    // コーナーに複数のウィジェットを配置するためのコンテナウィジェットを作成
    QWidget *cornerContainer = new QWidget();
    QHBoxLayout *cornerLayout = new QHBoxLayout(cornerContainer);
    cornerLayout->setContentsMargins(0, 0, 0, 0); // コーナーウィジェットのマージンをゼロに設定
    cornerLayout->setSpacing(2); // ウィジェット間のスペース

    // 最初のコーナーウィジェット
    QPushButton *refreshButton = new QPushButton("R");
    refreshButton->setFixedSize(20, 20); // サイズを固定
    refreshButton->setToolTip("更新");

    // 2番目のコーナーウィジェット
    QLabel *infoLabel = new QLabel("i");
    infoLabel->setFixedSize(20, 20);
    infoLabel->setAlignment(Qt::AlignCenter);
    infoLabel->setStyleSheet("background-color: yellow; border: 1px solid orange;");
    infoLabel->setToolTip("情報");

    cornerLayout->addWidget(refreshButton);
    cornerLayout->addWidget(infoLabel);

    // コンテナウィジェットをコーナーウィジェットとして設定
    scrollArea->setCornerWidget(cornerContainer);

    scrollArea->show();

    return a.exec();
}

説明

  • 最後に、この cornerContainersetCornerWidget() に渡しています。これにより、2つのウィジェットが並んで右下隅に表示されます。
  • cornerLayout->setContentsMargins(0, 0, 0, 0); は、コーナーウィジェット自体の余白をなくすために重要です。
  • refreshButtoninfoLabel という2つのウィジェットを作成し、cornerContainer のレイアウトに追加しています。
  • cornerContainer という新しい QWidget を作成し、その中に QHBoxLayout を設定しています。

実行時にコーナーウィジェットを変更することも可能です。

#include <QApplication>
#include <QScrollArea>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#include <QTimer> // タイマー用
#include <QDebug>

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

    QScrollArea *scrollArea = new QScrollArea();
    scrollArea->setWindowTitle("動的コーナーウィジェットの例");
    scrollArea->resize(300, 400);

    // コンテンツウィジェット (省略)
    QWidget *contentWidget = new QWidget();
    QVBoxLayout *contentLayout = new QVBoxLayout(contentWidget);
    for (int i = 0; i < 40; ++i) {
        contentLayout->addWidget(new QPushButton(QString("コンテンツ %1").arg(i + 1)));
    }
    contentWidget->setLayout(contentLayout);
    scrollArea->setWidget(contentWidget);
    scrollArea->setWidgetResizable(true);

    // 最初に設定するコーナーウィジェット
    QPushButton *button1 = new QPushButton("状態 A");
    button1->setStyleSheet("background-color: lightgreen;");
    scrollArea->setCornerWidget(button1);

    // 3秒後にコーナーウィジェットを別のものに変更するタイマー
    QTimer::singleShot(3000, [scrollArea]() {
        qDebug() << "3秒経過: コーナーウィジェットを変更します。";
        // 新しいコーナーウィジェット
        QPushButton *button2 = new QPushButton("状態 B");
        button2->setStyleSheet("background-color: lightcoral;");

        // 既存のコーナーウィジェットを取得し、deleteLater() で削除をスケジュール
        // setCornerWidget() を呼び出すと、以前のウィジェットは自動的に親から切り離されますが、
        // メモリリークを防ぐために明示的に削除をスケジュールすることが推奨されます。
        QWidget *oldWidget = scrollArea->cornerWidget();
        if (oldWidget) {
            oldWidget->deleteLater();
            qDebug() << "前のコーナーウィジェットを削除対象にしました。";
        }

        // 新しいウィジェットを設定
        scrollArea->setCornerWidget(button2);
        qDebug() << "新しいコーナーウィジェットを設定しました。";
    });

    scrollArea->show();

    return a.exec();
}
  • 重要な点として、以前設定されていたウィジェット (oldWidget) は、setCornerWidget() が呼び出されると自動的に親ウィジェットから外されますが、メモリリークを防ぐために deleteLater() を呼び出して明示的に削除をスケジュールすることが推奨されます。
  • ラムダ式内で新しいボタン (button2) を作成し、setCornerWidget() で設定します。
  • QTimer::singleShot を使用して、3秒後にラムダ式を実行します。
  • 初期状態では「状態 A」のボタンがコーナーに表示されます。


以下に、cornerWidget() の代替となるプログラミング手法をいくつか紹介します。

QGridLayout や QVBoxLayout/QHBoxLayout を使って手動でレイアウトする

これは最も一般的で柔軟な代替手段です。QScrollArea を直接使わず、他のウィジェットと一緒にレイアウトマネージャーの中に配置することで、より詳細な位置とサイズ制御が可能になります。

メリット

  • コーナーウィジェットの自動的なサイズ調整に縛られない。
  • 複数のウィジェットを自由に配置できる。
  • レイアウトマネージャーの柔軟性により、ウィジェットのサイズ変更挙動を詳細に制御できる。
  • 任意の場所にウィジェットを配置できる。

デメリット

  • スクロールエリアと他のウィジェットが常に同じウィンドウに表示される場合にのみ適している。
  • スクロールバーの表示/非表示に応じて、手動でレイアウトを調整する必要がある場合がある(QScrollArea の自動的な調整がなくなるため)。

コード例

#include <QApplication>
#include <QWidget>
#include <QGridLayout>
#include <QScrollArea>
#include <QPushButton>
#include <QLabel>
#include <QVBoxLayout>

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

    QWidget *window = new QWidget();
    window->setWindowTitle("手動レイアウトの例");

    // メインのグリッドレイアウト
    QGridLayout *mainLayout = new QGridLayout(window);
    mainLayout->setContentsMargins(0, 0, 0, 0); // ウィンドウのマージンをゼロに

    // スクロールするコンテンツ (QScrollArea を使用)
    QScrollArea *scrollArea = new QScrollArea();
    QWidget *contentWidget = new QWidget();
    QVBoxLayout *contentLayout = new QVBoxLayout(contentWidget);
    for (int i = 0; i < 50; ++i) {
        contentLayout->addWidget(new QPushButton(QString("コンテンツボタン %1").arg(i + 1)));
    }
    contentWidget->setLayout(contentLayout);
    scrollArea->setWidget(contentWidget);
    scrollArea->setWidgetResizable(true);

    // グリッドレイアウトにスクロールエリアを配置 (例: 左上)
    mainLayout->addWidget(scrollArea, 0, 0, 1, 1); // Row 0, Col 0, 1行1列を占有

    // 隅に配置したいウィジェット (例: 右下)
    QPushButton *myCornerButton = new QPushButton("私のボタン");
    myCornerButton->setFixedSize(60, 25); // 固定サイズを設定

    // グリッドレイアウトの適切な位置に配置
    // 例えば、スクロールエリアの右下隅に相当する位置に配置
    // 通常、これはスクロールエリアと隣接するセルになる
    // この例では、スクロールエリアの右側にボタンを配置し、縦方向にスクロールバーが来たときに隣接するようにする
    // ただし、これだとQAbstractScrollArea::cornerWidget()の「スクロールバーが交差する位置」とは意味合いが異なる
    // 完全に同じ位置に配置するには、scrollArea自体の中にQGridLayoutを使い、より複雑なレイアウトが必要になる。

    // より正確にスクロールエリアの「隅」を模倣するなら、
    // スクロールエリアの中にQGridLayoutを配置し、ビューポートとスクロールバーを模倣する。
    // しかし、それはQScrollAreaを使う意味が薄れるため、この方法ではあまり推奨されない。
    // 一般的には、スクロールエリアの隣に補助的なウィジェットを置く場合に使う。

    // 例として、右側に別のウィジェットを配置
    QLabel *sideInfoLabel = new QLabel("情報");
    sideInfoLabel->setStyleSheet("background-color: lightblue; padding: 5px;");
    mainLayout->addWidget(sideInfoLabel, 0, 1, Qt::AlignTop | Qt::AlignRight); // 右上に配置

    // もし、scrollAreaの右下に正確に重ねたい場合、
    // QStackedLayoutやQOverlayLayout(自作)を使う、またはイベントフィルタで手動で位置を計算する
    // という複雑な方法になる。

    // QAbstractScrollArea::cornerWidget() が提供する「スクロールバーの交差部分」に
    // 完全に相当するレイアウトは、QScrollAreaを使っている限り、手動で実現するのは非常に難しい。
    // この代替案は、「スクロールエリアの横や下などに補助的なウィジェットを配置したい」場合に有効。

    window->setLayout(mainLayout);
    window->resize(400, 450);
    window->show();

    return a.exec();
}

考察
上記の例では、QScrollArea とボタンをメインのグリッドレイアウトの異なるセルに配置しています。これは QAbstractScrollArea::cornerWidget() が提供する「スクロールバーが交差する隅」という特定の位置とは意味合いが異なります。

cornerWidget() と全く同じ挙動(スクロールバーの有無に応じてウィジェットがその交差部分に現れる)を、純粋な QGridLayout だけで実現するのは非常に困難です。なぜなら、QScrollArea の内部的なスクロールバーのレイアウトは複雑で、その特定の位置に他のウィジェットを「挿入」するような機能は提供されていないからです。

この代替案は、むしろ「スクロールエリアの外側に、その機能に関連するボタンや情報表示を置きたい」場合に適しています。

QGraphicsView/QGraphicsScene を使用する

非常に複雑な描画や、カスタムレイアウト、インタラクティブな要素が必要な場合は、QGraphicsViewQGraphicsScene のフレームワークを使用することを検討できます。

メリット

  • スクロールバーの表示/非表示も、QGraphicsViewsetViewportUpdateMode()setSceneRect() などで制御できる。
  • カスタムのインタラクションやアニメーションを簡単に実装できる。
  • 大量のアイテムを効率的に管理できる。
  • 完全に自由な描画と配置が可能。

デメリット

  • 標準ウィジェットの見た目や挙動を模倣する場合、手動で実装する必要がある。
  • シンプルな用途にはオーバースペック。
  • 学習コストが高い。

コード例 (概念のみ)

// 非常に概念的なコード。実際には多くの実装が必要。
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QGraphicsProxyWidget> // QWidgetをGraphicsSceneに埋め込む
#include <QPushButton>

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

    QGraphicsScene *scene = new QGraphicsScene();
    QGraphicsView *view = new QGraphicsView(scene);
    view->setWindowTitle("QGraphicsViewでのカスタムコーナーの例");

    // 大量の長方形アイテムをシーンに追加してスクロールさせる
    for (int i = 0; i < 50; ++i) {
        QGraphicsRectItem *rect = new QGraphicsRectItem(0, i * 30, 200, 25);
        rect->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
        scene->addItem(rect);
    }
    // シーンの範囲を設定(スクロールバーの表示に影響)
    scene->setSceneRect(0, 0, 200, 1500);

    // コーナーに配置したいウィジェット (例: ボタン)
    QPushButton *cornerBtn = new QPushButton("ビューボタン");
    // QGraphicsProxyWidget を使って QWidget を QGraphicsScene に追加
    QGraphicsProxyWidget *proxy = scene->addWidget(cornerBtn);

    // ボタンの位置を手動で設定
    // これはviewのサイズとスクロールバーの幅を考慮する必要がある
    // viewのresizeイベントやスクロールバーの表示状態に応じて動的に位置を計算するロジックが必要
    proxy->setPos(view->width() - cornerBtn->width() - view->verticalScrollBar()->width(),
                  view->height() - cornerBtn->height() - view->horizontalScrollBar()->height());

    // 実際のアプリケーションでは、viewのサイズ変更イベントやスクロールバーの表示/非表示イベントを監視し、
    // proxyの位置を動的に更新する必要があります。
    // view->installEventFilter(some_object); など

    view->resize(400, 400);
    view->show();

    return a.exec();
}

考察
QGraphicsView は非常に強力ですが、cornerWidget() の代替としては、単純なユースケースには過剰です。主に、描画要素が豊富で、カスタムのスクロールやズーム、インタラクションが求められる場合に有効です。

これは最も低レベルな方法で、スクロールエリアの resizeEvent やスクロールバーの valueChanged イベントを監視し、それに基づいてウィジェットを手動で配置します。

メリット

  • 特定のフレームワークに依存しない。
  • 究極の柔軟性。どんなウィジェットでも、どんな場所でも、どんな条件でも配置できる。

デメリット

  • パフォーマンスに影響を与える可能性もある。
  • スクロールバーの幅/高さ、表示状態、ウィンドウのサイズ変更など、多くの要因を考慮する必要がある。
  • 実装が非常に複雑で、バグが発生しやすい。

コード例 (概念のみ)

// これは非常に複雑で、完全な実装は困難です。
// 通常、QAbstractScrollArea::cornerWidget() が使えない、
// またはQGraphicsView/QGraphicsSceneでも対応できない非常に特殊な場合にのみ検討すべきです。
#include <QApplication>
#include <QScrollArea>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#include <QEvent>
#include <QScrollBar>
#include <QDebug>

class MyScrollArea : public QScrollArea
{
    Q_OBJECT
public:
    MyScrollArea(QWidget *parent = nullptr) : QScrollArea(parent)
    {
        myCustomCornerWidget = new QPushButton("カスタム");
        myCustomCornerWidget->setParent(this); // 親をスクロールエリアに設定
        myCustomCornerWidget->hide(); // 初期状態では非表示

        // スクロールバーのイベントを監視 (値変更、表示/非表示など)
        verticalScrollBar()->installEventFilter(this);
        horizontalScrollBar()->installEventFilter(this);
    }

protected:
    void resizeEvent(QResizeEvent *event) override
    {
        QScrollArea::resizeEvent(event);
        updateCornerWidgetPosition();
    }

    bool eventFilter(QObject *obj, QEvent *event) override
    {
        if (obj == verticalScrollBar() || obj == horizontalScrollBar()) {
            if (event->type() == QEvent::Show || event->type() == QEvent::Hide || event->type() == QEvent::Resize) {
                updateCornerWidgetPosition();
            }
        }
        return QScrollArea::eventFilter(obj, event);
    }

private:
    void updateCornerWidgetPosition()
    {
        bool vScrollVisible = verticalScrollBar()->isVisible();
        bool hScrollVisible = horizontalScrollBar()->isVisible();

        if (vScrollVisible && hScrollVisible) {
            myCustomCornerWidget->show();
            int vBarWidth = verticalScrollBar()->width();
            int hBarHeight = horizontalScrollBar()->height();

            // スクロールエリアのビューポートの右下隅に配置
            // ビューポートの右下隅 = (幅 - vBarWidth, 高さ - hBarHeight)
            // myCustomCornerWidget は QScrollArea の子なので、その座標系で位置を設定
            myCustomCornerWidget->setGeometry(width() - vBarWidth,
                                              height() - hBarHeight,
                                              vBarWidth,
                                              hBarHeight); // スクロールバーと同じサイズに

            qDebug() << "コーナーウィジェット位置:" << myCustomCornerWidget->geometry();
        } else {
            myCustomCornerWidget->hide();
        }
    }

    QPushButton *myCustomCornerWidget;
};

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

    MyScrollArea *scrollArea = new MyScrollArea();
    scrollArea->setWindowTitle("手動配置のコーナーウィジェットの例");
    scrollArea->resize(300, 400);

    QWidget *contentWidget = new QWidget();
    QVBoxLayout *contentLayout = new QVBoxLayout(contentWidget);
    for (int i = 0; i < 50; ++i) {
        contentLayout->addWidget(new QPushButton(QString("コンテンツ %1").arg(i + 1)));
    }
    contentWidget->setLayout(contentLayout);
    scrollArea->setWidget(contentWidget);
    scrollArea->setWidgetResizable(true);

    scrollArea->show();

    return a.exec();
}
#include "main.moc" // mocファイルをインクルード

考察
このアプローチは非常に複雑で、QAbstractScrollArea::cornerWidget() が提供する機能を再実装しているに過ぎません。特別な理由がない限り、推奨されません。

代替方法メリットデメリット適したシナリオ
QGridLayout などで手動レイアウト柔軟な配置、複数ウィジェット対応、細かなサイズ制御スクロールバー表示に応じた手動調整が必要、cornerWidget() の正確な位置再現は困難スクロールエリアの外側に補助ウィジェットを配置したい場合
QGraphicsView/QGraphicsScene自由な描画、大量アイテム、カスタムインタラクション学習コスト高、シンプル用途にはオーバースペック複雑なグラフィック、カスタムスクロール、インタラクティブな描画が必要な場合
イベントフィルタと手動配置究極の柔軟性非常に複雑、バグ発生リスク高、パフォーマンス懸念他のどの方法でも実現できない非常に特殊なケース