Qtでカスタマイズ自在なタブUIを実現:QTabWidgetの代替手段を比較

2025-05-27

Qtプログラミングにおける QTabWidget::QTabWidget() は、QTabWidget クラスのコンストラクタを指します。

これは、新しい QTabWidget オブジェクトを作成する際に呼び出される特別な関数です。

C++の構文では、クラス名::クラス名() の形式は、そのクラスのコンストラクタを表します。

QTabWidget とは?

QTabWidget は、ユーザーインターフェースで複数の「タブ」を持つウィジェットを作成するためのQtのクラスです。各タブは異なる内容(別のウィジェット)を表示することができ、ユーザーはタブをクリックすることで表示される内容を切り替えることができます。

QTabWidget::QTabWidget() の機能

QTabWidget には主に以下のコンストラクタがあります(よく使われるもの):

  • QTabWidget(QWidget *parent = nullptr):
    • このコンストラクタが最も一般的です。
    • parent 引数はオプションで、新しく作成される QTabWidget の親ウィジェットを指定します。
    • parent を指定すると、この QTabWidget は親ウィジェットの内部に配置され、親が削除されると自動的にこの QTabWidget も削除されます(Qtのオブジェクトツリーの概念)。
    • nullptr (または 0) を指定した場合、この QTabWidget は独立したトップレベルウィンドウとして作成されます。

例えば、Qt/C++で QTabWidget を作成する際には、以下のように記述します。

#include <QApplication>
#include <QTabWidget>
#include <QWidget>
#include <QLabel>
#include <QVBoxLayout>

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

    // QTabWidgetを作成(親はnullptrなので、独立したウィンドウとして表示される)
    QTabWidget *tabWidget = new QTabWidget();

    // 各タブのページとなるウィジェットを作成
    QWidget *page1 = new QWidget();
    QVBoxLayout *layout1 = new QVBoxLayout(page1);
    layout1->addWidget(new QLabel("これはタブ1のコンテンツです。"));
    page1->setLayout(layout1); // レイアウトを設定

    QWidget *page2 = new QWidget();
    QVBoxLayout *layout2 = new QVBoxLayout(page2);
    layout2->addWidget(new QLabel("これはタブ2のコンテンツです。"));
    page2->setLayout(layout2); // レイアウトを設定

    // タブとページを追加
    tabWidget->addTab(page1, "タブ1");
    tabWidget->addTab(page2, "タブ2");

    // ウィンドウのタイトルを設定
    tabWidget->setWindowTitle("QTabWidgetの例");

    // ウィンドウを表示
    tabWidget->show();

    return app.exec();
}


QTabWidget::QTabWidget() に直接関連するエラー(稀)

  1. コンパイラエラー:undefined reference to 'QTabWidget::QTabWidget(QWidget*)' など
    • 原因
      QTabWidget を使用するために必要なQtモジュール(通常は QtWidgets)がプロジェクトのビルド設定に正しく含まれていない場合に発生します。
    • トラブルシューティング
      • .pro ファイル(QMakeを使用している場合)に QT += widgets を追加しているか確認してください。
      • CMakeを使用している場合、find_package(Qt6 COMPONENTS Widgets REQUIRED)find_package(Qt5 COMPONENTS Widgets REQUIRED) のように記述し、target_link_librariesQt6::Widgets または Qt5::Widgets をリンクしているか確認してください。
      • ヘッダファイルが正しくインクルードされているか確認してください (#include <QTabWidget>)。

QTabWidget のコンストラクタ自体よりも、その後のタブの追加や管理、レイアウト、スタイルに関する問題が多いです。

    • 原因
      • タブに追加したウィジェットが適切にレイアウトされていない。
      • タブに追加したウィジェットの親が意図しないものになっている。
      • タブウィジェット自体が表示されていない、または親ウィジェットが非表示になっている。
    • トラブルシューティング
      • tabWidget->addTab(widget, "Tab Name"); で追加した widget が、内部に適切なレイアウト(QVBoxLayout, QHBoxLayout, QGridLayout など)を持ち、そのレイアウトに子ウィジェットが追加されていることを確認してください。
      • widget->setLayout(myLayout); のように、必ずウィジェットにレイアウトを設定してください。
      • tabWidget->show(); またはその親ウィジェットが show() されているか確認してください。
      • デバッガを使って、追加したウィジェットのポインタがnullptrになっていないか、オブジェクトが生存しているかを確認してください。
  1. タブのコンテンツが期待通りにリサイズされない

    • 原因
      • タブの各ページ(ウィジェット)が適切なサイズポリシー(QSizePolicy)を持っていない。
      • 親のレイアウトがコンテンツのサイズ変更を適切に扱っていない。
    • トラブルシューティング
      • 各タブページ内のウィジェットに setSizePolicy() を設定し、ExpandingPreferred などを適切に設定してください。
      • タブウィジェット自体やその親のレイアウト(例: mainLayout->addWidget(tabWidget);)が適切に設定され、リサイズイベントを処理できることを確認してください。
  2. タブの切り替え時にメモリリークが発生する(古いQtのコードで稀)

    • 原因
      • removeTab() などでタブを削除した際に、タブ内のウィジェットが適切に削除されていない(手動で delete する必要がある場合があるが、Qtのオブジェクトツリーに任せるのが一般的)。
    • トラブルシューティング
      • QTabWidget に追加されたウィジェットは、通常 QTabWidget が親となるため、QTabWidget が削除される際に自動的に子ウィジェットも削除されます。明示的に delete する必要があるケースは稀ですが、もし手動でタブを削除していてメモリリークが疑われる場合は、removeTab() の後、タブ内のウィジェットも deleteLater() などで削除をスケジュールする必要があるかもしれません。しかし、これはQtの通常のオブジェクトツリーの管理から外れるため、慎重に行うべきです。
  3. タブの表示が乱れる、スタイルが適用されない

    • 原因
      • スタイルシート(QSS)の記述が間違っている、または優先順位の問題。
      • Qtスタイルの競合。
    • トラブルシューティング
      • QSSを適用している場合、セレクタが正しいか (QTabWidget, QTabBar, QTabBar::tab など)。
      • QSSのルールが他のスタイルやネイティブスタイルと競合していないか確認してください。
      • 単純なスタイル(背景色など)から試して、徐々に複雑なスタイルを適用していくと、問題の切り分けがしやすくなります。
  4. addTab() で同じウィジェットを複数回追加してしまう

    • 原因
      同じウィジェットインスタンスを異なるタブとして追加しようとすると、Qtはエラーを出すか、最後に設定されたタブにしか表示されなくなります。
    • トラブルシューティング
      各タブには異なるウィジェットインスタンスを割り当てる必要があります。
      // 悪い例
      QWidget *commonPage = new QWidget();
      tabWidget->addTab(commonPage, "タブ1");
      tabWidget->addTab(commonPage, "タブ2"); // これだとタブ2にしか表示されない
      
      // 良い例
      QWidget *page1 = new QWidget();
      QWidget *page2 = new QWidget();
      tabWidget->addTab(page1, "タブ1");
      tabWidget->addTab(page2, "タブ2");
      
  5. タブの削除(removeTab())後のインデックスの扱いの誤り

    • 原因
      removeTab() を呼び出すと、それ以降のタブのインデックスが変わります。ループ内で削除を行う際に、インデックスの調整を怠ると予期せぬ動作やクラッシュを引き起こす可能性があります。
    • トラブルシューティング
      後ろのタブから削除するか、削除後にインデックスを適切にデクリメントする、または takeWidget() を使用してウィジェットを取り出し、その後必要に応じてウィジェットを削除するなど、安全な方法でタブを削除してください。


以下に、QTabWidget::QTabWidget() を使用したプログラミングの典型的な例をいくつか示します。

基本的な QTabWidget の作成とタブの追加

この例では、QTabWidget を作成し、2つの基本的なタブ(それぞれ QLabel を含む)を追加する方法を示します。

#include <QApplication> // アプリケーションのイベントループを管理
#include <QTabWidget>   // タブウィジェット
#include <QWidget>      // 各タブのページとなる汎用ウィジェット
#include <QLabel>       // テキストを表示するウィジェット
#include <QVBoxLayout>  // 垂直方向のレイアウト

int main(int argc, char *argv[]) {
    QApplication app(argc, argv); // QApplicationオブジェクトを初期化

    // QTabWidgetを作成。親を指定しないため、独立したウィンドウとして表示されます。
    QTabWidget *tabWidget = new QTabWidget();

    // --- タブ1のコンテンツを作成 ---
    QWidget *page1 = new QWidget(); // タブ1のページとなるウィジェット
    QVBoxLayout *layout1 = new QVBoxLayout(page1); // ページ1のレイアウト
    QLabel *label1 = new QLabel("これはタブ1のコンテンツです。");
    layout1->addWidget(label1); // レイアウトにラベルを追加
    // page1->setLayout(layout1); // コンストラクタで親を指定したので、この行は不要だが、明示的に設定することも可能

    // --- タブ2のコンテンツを作成 ---
    QWidget *page2 = new QWidget(); // タブ2のページとなるウィジェット
    QVBoxLayout *layout2 = new QVBoxLayout(page2); // ページ2のレイアウト
    QLabel *label2 = new QLabel("これはタブ2のコンテンツです。\nもう1つの行を追加します。");
    layout2->addWidget(label2); // レイアウトにラベルを追加

    // QTabWidgetにタブとページを追加
    tabWidget->addTab(page1, "最初のタブ"); // page1を「最初のタブ」として追加
    tabWidget->addTab(page2, "二番目のタブ"); // page2を「二番目のタブ」として追加

    // ウィンドウのタイトルを設定
    tabWidget->setWindowTitle("QTabWidgetのシンプルな例");
    // ウィンドウの初期サイズを設定
    tabWidget->resize(400, 300);

    // ウィンドウを表示
    tabWidget->show();

    return app.exec(); // アプリケーションのイベントループを開始
}

解説

  • tabWidget->addTab(page1, "最初のタブ");
    • 作成した page1tabWidget に追加し、そのタブの表示名を "最初のタブ" としています。
  • QVBoxLayout *layout1 = new QVBoxLayout(page1);
    • page1 の内部にウィジェットを配置するために、QVBoxLayout (垂直レイアウト) を使用しています。コンストラクタで親 (page1) を指定することで、レイアウトが自動的に page1 に設定されます。
  • QWidget *page1 = new QWidget();
    • 各タブの中身となるウィジェットを作成します。QTabWidget は、タブごとに1つの QWidget を「ページ」として持ちます。このページの中に、さらに好きなウィジェットやレイアウトを配置できます。
  • QTabWidget *tabWidget = new QTabWidget();
    • これが QTabWidget のコンストラクタを呼び出す部分です。ここでは親ウィジェットを nullptr (デフォルト) としているので、tabWidget は独立したトップレベルウィンドウとして表示されます。

親ウィジェットを持つ QTabWidget の作成

QTabWidget を他のウィンドウやウィジェットの一部として使用する場合、親ウィジェットを指定してコンストラクタを呼び出します。

#include <QApplication>
#include <QMainWindow>  // メインウィンドウ
#include <QTabWidget>
#include <QWidget>
#include <QLabel>
#include <QPushButton>  // ボタン
#include <QVBoxLayout>
#include <QHBoxLayout>  // 水平方向のレイアウト

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

    QMainWindow *mainWindow = new QMainWindow(); // メインウィンドウを作成
    QWidget *centralWidget = new QWidget(mainWindow); // メインウィンドウの中央ウィジェット
    QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget); // 中央ウィジェットのレイアウト

    // QTabWidgetを作成し、親としてcentralWidgetを指定
    QTabWidget *tabWidget = new QTabWidget(centralWidget);

    // --- タブ1のコンテンツ ---
    QWidget *pageA = new QWidget();
    QVBoxLayout *layoutA = new QVBoxLayout(pageA);
    layoutA->addWidget(new QLabel("これは設定ページです。"));
    layoutA->addWidget(new QPushButton("設定を保存"));

    // --- タブ2のコンテンツ ---
    QWidget *pageB = new QWidget();
    QHBoxLayout *layoutB = new QHBoxLayout(pageB);
    layoutB->addWidget(new QLabel("これはログ表示ページです。"));
    layoutB->addWidget(new QLineEdit()); // テキスト入力フィールド

    // タブを追加
    tabWidget->addTab(pageA, "設定");
    tabWidget->addTab(pageB, "ログ");

    // メインレイアウトにQTabWidgetを追加
    mainLayout->addWidget(tabWidget);

    // メインウィンドウに中央ウィジェットを設定
    mainWindow->setCentralWidget(centralWidget);
    mainWindow->setWindowTitle("親を持つQTabWidgetの例");
    mainWindow->resize(600, 400);
    mainWindow->show();

    return app.exec();
}

解説

  • mainLayout->addWidget(tabWidget);
    • centralWidget のレイアウトに tabWidget を追加することで、tabWidgetcentralWidget 内に表示されるようになります。
  • QTabWidget *tabWidget = new QTabWidget(centralWidget);
    • この行が、QTabWidget のコンストラクタに centralWidget を親として渡している部分です。これにより、tabWidgetcentralWidget の子となり、メインウィンドウの内部に配置されます。親が設定されている場合、通常は親ウィジェットのレイアウトに子ウィジェットを追加して配置を管理します。

addTab() オーバーロードを使用して、タブにアイコンを追加することもできます。

#include <QApplication>
#include <QMainWindow>
#include <QTabWidget>
#include <QWidget>
#include <QLabel>
#include <QIcon>        // アイコン
#include <QVBoxLayout>

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

    QTabWidget *tabWidget = new QTabWidget();

    // アイコンの準備(実際のアプリケーションではパスを適切に指定します)
    // 例えば、Qtプロジェクトフォルダ内の "icons" ディレクトリに "settings.png" と "info.png" がある場合
    QIcon settingsIcon(":/icons/settings.png"); // リソースファイルから読み込む場合
    QIcon infoIcon(":/icons/info.png");         // リソースファイルから読み込む場合
    // または、ローカルファイルから読み込む場合
    // QIcon settingsIcon("settings.png");
    // QIcon infoIcon("info.png");

    // タブ1のコンテンツ
    QWidget *page1 = new QWidget();
    QVBoxLayout *layout1 = new QVBoxLayout(page1);
    layout1->addWidget(new QLabel("設定に関する情報。"));

    // タブ2のコンテンツ
    QWidget *page2 = new QWidget();
    QVBoxLayout *layout2 = new QVBoxLayout(page2);
    layout2->addWidget(new QLabel("アプリケーションの情報。"));

    // アイコン付きでタブを追加
    tabWidget->addTab(page1, settingsIcon, "設定"); // アイコンとテキスト
    tabWidget->addTab(page2, infoIcon, "情報");     // アイコンとテキスト

    tabWidget->setWindowTitle("アイコン付きQTabWidgetの例");
    tabWidget->resize(400, 300);
    tabWidget->show();

    return app.exec();
}
  • tabWidget->addTab(page1, settingsIcon, "設定");
    • addTab() のオーバーロードを使用して、QIcon オブジェクトを2番目の引数として渡すことで、タブのタイトルにアイコンが表示されるようになります。
  • QIcon settingsIcon(":/icons/settings.png");
    • Qtのリソースシステム (.qrc ファイル) を使用してアイコンを埋め込んでいる場合のパスの例です。プロジェクトに icons.qrc というファイルがあり、その中に settings.png が登録されていると仮定しています。


QStackedWidget と QTabBar の組み合わせ

これは QTabWidget の内部的な実装に近い方法であり、最も一般的な代替手段です。

  • QTabBar: タブの形状とクリックイベントを処理するウィジェットです。タブの視覚的な部分だけを提供し、中身の表示は行いません。
  • QStackedWidget: 複数のウィジェットを重ねて表示し、一度に1つのウィジェットだけを表示するコンテナウィジェットです。

利点

  • カスタムUIの作成
    QTabBar をサブクラス化して paintEvent をオーバーライドすれば、完全に独自のタブの見た目をデザインできます。
  • イベントの制御
    QTabBar が提供するシグナル(例:tabBarClicked(int index))を直接受け取り、QStackedWidgetsetCurrentIndex(int index) スロットに接続することで、タブの切り替えを完全に制御できます。
  • 高い柔軟性
    QTabWidget では難しいような、タブの配置(例:左右にタブバーを置く)、タブの表示内容(例:タブにボタンを置く)、タブとコンテンツの連動方法(例:タブの切り替え時にアニメーションを加える)などを細かく制御できます。

欠点

  • 実装の手間
    QTabWidget と比較して、タブバーとスタックウィジェットの連携を自分で記述する必要があるため、コード量が増えます。

コード例

#include <QApplication>
#include <QMainWindow>
#include <QStackedWidget> // ページを重ねて表示するウィジェット
#include <QTabBar>        // タブの見た目を提供するウィジェット
#include <QLabel>
#include <QVBoxLayout>

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

    QMainWindow *mainWindow = new QMainWindow();
    QWidget *centralWidget = new QWidget(mainWindow);
    QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget);

    // QTabBarを作成
    QTabBar *tabBar = new QTabBar();
    tabBar->addTab("設定");
    tabBar->addTab("情報");
    tabBar->addTab("ヘルプ");

    // QStackedWidgetを作成
    QStackedWidget *stackedWidget = new QStackedWidget();

    // 各タブのページとなるウィジェットを作成し、QStackedWidgetに追加
    QWidget *page1 = new QWidget();
    QVBoxLayout *layout1 = new QVBoxLayout(page1);
    layout1->addWidget(new QLabel("これは設定ページです。"));
    stackedWidget->addWidget(page1); // QStackedWidgetに追加

    QWidget *page2 = new QWidget();
    QVBoxLayout *layout2 = new QVBoxLayout(page2);
    layout2->addWidget(new QLabel("これは情報ページです。"));
    stackedWidget->addWidget(page2); // QStackedWidgetに追加

    QWidget *page3 = new QWidget();
    QVBoxLayout *layout3 = new QVBoxLayout(page3);
    layout3->addWidget(new QLabel("これはヘルプページです。"));
    stackedWidget->addWidget(page3); // QStackedWidgetに追加

    // QTabBarの currentChanged シグナルと QStackedWidget の setCurrentIndex スロットを接続
    // これにより、タブがクリックされると対応するページが表示されます
    QObject::connect(tabBar, &QTabBar::currentChanged, stackedWidget, &QStackedWidget::setCurrentIndex);

    // メインレイアウトにタブバーとスタックウィジェットを追加
    mainLayout->addWidget(tabBar);
    mainLayout->addWidget(stackedWidget);

    mainWindow->setCentralWidget(centralWidget);
    mainWindow->setWindowTitle("QStackedWidget + QTabBarの例");
    mainWindow->resize(500, 350);
    mainWindow->show();

    return app.exec();
}

QMdiArea を使用したMDI (Multiple Document Interface) アプリケーション

タブ形式とは異なりますが、複数のドキュメントやビューを同時に開いて管理する代替手段としてMDIが挙げられます。

  • QMdiArea: 複数の QMdiSubWindow を管理するためのウィジェットです。各 QMdiSubWindow は独立した子ウィンドウとして振る舞い、重ねて表示したり、タイル状に並べたりできます。

利点

  • ドキュメント指向アプリケーション
    テキストエディタや画像編集ソフトなど、複数のドキュメントを同時に開くタイプのアプリケーションに適しています。
  • 柔軟なウィンドウ配置
    ユーザーが子ウィンドウを移動、リサイズ、最小化、最大化できるため、自由度の高いインターフェースを提供できます。

欠点

  • 実装の手間
    QTabWidget よりも、子ウィンドウの管理(作成、削除、アクティブ化)が複雑になります。
  • 複雑なUI
    多くのドキュメントが開かれると、デスクトップが煩雑になる可能性があります。
#include <QApplication>
#include <QMainWindow>
#include <QMdiArea>         // MDI領域
#include <QMdiSubWindow>    // MDI子ウィンドウ
#include <QTextEdit>        // テキストエディタの例
#include <QMenuBar>
#include <QAction>

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

    QMainWindow *mainWindow = new QMainWindow();
    QMdiArea *mdiArea = new QMdiArea(); // MDIエリアを作成
    mainWindow->setCentralWidget(mdiArea); // メインウィンドウの中央ウィジェットとして設定

    // メニューバーに「ファイル」メニューを追加
    QMenu *fileMenu = mainWindow->menuBar()->addMenu("ファイル");
    QAction *newAction = fileMenu->addAction("新規作成");

    // 「新規作成」アクションがトリガーされたときの処理
    QObject::connect(newAction, &QAction::triggered, [mdiArea]() {
        QMdiSubWindow *subWindow = new QMdiSubWindow(); // 新しい子ウィンドウを作成
        QTextEdit *editor = new QTextEdit(); // 子ウィンドウのコンテンツ
        subWindow->setWidget(editor); // コンテンツを子ウィンドウに設定
        subWindow->setWindowTitle("新しいドキュメント");
        mdiArea->addSubWindow(subWindow); // MDIエリアに子ウィンドウを追加
        subWindow->show(); // 子ウィンドウを表示
    });

    mainWindow->setWindowTitle("MDIアプリケーションの例");
    mainWindow->resize(800, 600);
    mainWindow->show();

    return app.exec();
}

QToolBox を使用した折りたたみ可能なセクション

タブ形式とは少し異なりますが、スペースを節約し、異なるセクション間で切り替えたい場合に有効な代替手段です。

  • QToolBox: 複数のページを重ねて表示し、各ページのタイトル部分をクリックすることでページを折りたたんだり展開したりできるウィジェットです。

利点

  • 視覚的な整理
    関連性の高い情報をグループ化し、見出しで明確に区別できます。
  • 省スペース
    一度に1つのセクションだけが完全に表示されるため、限られたスペースで多くの情報を整理するのに役立ちます。

欠点

  • タブのような「並列」な情報の切り替えには不向きです。あくまで「セクションの展開・折りたたみ」というインタラクションになります。

コード例

#include <QApplication>
#include <QMainWindow>
#include <QToolBox>     // ツールボックスウィジェット
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>

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

    QToolBox *toolBox = new QToolBox(); // QToolBoxを作成

    // --- ページ1のコンテンツ ---
    QWidget *page1 = new QWidget();
    QVBoxLayout *layout1 = new QVBoxLayout(page1);
    layout1->addWidget(new QLabel("ユーザー設定をここで行います。"));
    layout1->addWidget(new QPushButton("プロフィール編集"));

    // --- ページ2のコンテンツ ---
    QWidget *page2 = new QWidget();
    QVBoxLayout *layout2 = new QVBoxLayout(page2);
    layout2->addWidget(new QLabel("システムの詳細情報です。"));
    layout2->addWidget(new QLabel("バージョン: 1.0.0"));

    // --- ページ3のコンテンツ ---
    QWidget *page3 = new QWidget();
    QVBoxLayout *layout3 = new QVBoxLayout(page3);
    layout3->addWidget(new QLabel("お問い合わせ先は以下の通りです。"));
    layout3->addWidget(new QLabel("サポート電話: XXX-XXXX"));

    // QToolBoxにページを追加
    toolBox->addItem(page1, "アカウント"); // ページとタイトル
    toolBox->addItem(page2, "システム情報");
    toolBox->addItem(page3, "ヘルプとサポート");

    toolBox->setWindowTitle("QToolBoxの例");
    toolBox->resize(300, 400);
    toolBox->show();

    return app.exec();
}

QTabBar 以外のウィジェット(例:QListWidgetQComboBoxQButtonGroup に複数の QPushButton)を使って、QStackedWidget のページを切り替える方法です。

  • 非標準的なナビゲーション
    タブ以外の視覚的な要素(リストアイテム、ツリービュー、ラジオボタンなど)でコンテンツを切り替えたい場合に適しています。
  • 自由なデザイン
    ナビゲーション部分を完全にカスタマイズできるため、アプリケーションの全体的なテーマやブランドに合わせやすいです。
#include <QApplication>
#include <QMainWindow>
#include <QStackedWidget>
#include <QListWidget> // 左側のナビゲーションリスト
#include <QLabel>
#include <QVBoxLayout>
#include <QHBoxLayout>

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

    QMainWindow *mainWindow = new QMainWindow();
    QWidget *centralWidget = new QWidget(mainWindow);
    QHBoxLayout *mainLayout = new QHBoxLayout(centralWidget);

    QListWidget *navigationList = new QListWidget(); // ナビゲーションリストを作成
    navigationList->addItem("ホーム");
    navigationList->addItem("設定");
    navigationList->addItem("通知");
    navigationList->setMaximumWidth(150); // 幅を制限

    QStackedWidget *stackedWidget = new QStackedWidget(); // コンテンツ表示エリア

    // 各ページのコンテンツ
    QWidget *homePage = new QWidget();
    QVBoxLayout *homeLayout = new QVBoxLayout(homePage);
    homeLayout->addWidget(new QLabel("ようこそ!"));
    stackedWidget->addWidget(homePage);

    QWidget *settingsPage = new QWidget();
    QVBoxLayout *settingsLayout = new QVBoxLayout(settingsPage);
    settingsLayout->addWidget(new QLabel("ユーザー設定画面です。"));
    stackedWidget->addWidget(settingsPage);

    QWidget *notificationsPage = new QWidget();
    QVBoxLayout *notificationsLayout = new QVBoxLayout(notificationsPage);
    notificationsLayout->addWidget(new QLabel("新しい通知はありません。"));
    stackedWidget->addWidget(notificationsPage);

    // リストアイテムの選択変更とスタックウィジェットのページ切り替えを接続
    QObject::connect(navigationList, &QListWidget::currentRowChanged,
                     stackedWidget, &QStackedWidget::setCurrentIndex);

    mainLayout->addWidget(navigationList);
    mainLayout->addWidget(stackedWidget);

    mainWindow->setCentralWidget(centralWidget);
    mainWindow->setWindowTitle("カスタムナビゲーションの例");
    mainWindow->resize(600, 400);
    mainWindow->show();

    // 初期表示として最初のアイテムを選択
    navigationList->setCurrentRow(0);

    return app.exec();
}