Qt をはじめよう! 第9回: レイアウト管理を学ぼう

QWidget の親子関係を学ぼう では子ウィジェットをもつ [qt QWidget] のサブクラス Example を作成しました。

その際、[qt QWidget setGeometry()] を使用して子ウィジェットの位置と大きさを指定したため、ウィンドウのサイズを変更した場合に表示が崩れるという問題がありました。今回はこの問題の解決策となる [qt "レイアウト管理" l=layout] について学びましょう。

レイアウト管理について

Qt におけるレイアウトの管理は [qt QLayout] から派生したクラスによって実現しており、自動的に最適なレイアウトを管理するために以下の機能を提供します。

  • 子ウィジェットの位置とサイズの設定
  • ウィンドウのデフォルトサイズの設定
  • ウィンドウの最小サイズの設定
  • リサイズ時のレイアウトの調整
  • フォントサイズやテキスト等のウィジェットの内容が変わった際のレイアウトの再構築
  • 子ウィジェットの表示/非表示が切り替わった際のレイアウトの再構築
  • 子ウィジェットの追加や削除時のレイアウトの再構築

Qt では以下に示す4つのレイアウトクラスが使用可能です。

  • [qt QHBoxLayout] … ウィジェットを水平方向に並べるためのレイアウト
  • [qt QVBoxLayout] … ウィジェットを垂直方向に並べるためのレイアウト
  • [qt QGridLayout] … ウィジェットを格子状に並べるためのレイアウト
  • [qt QFormLayout] … 複数の入力用のウィジェットをそれぞれのラベルと共に並べるためのレイアウト

各レイアウトの詳細については各クラスのドキュメントや [qt "Basic Layouts" l=layouts-basiclayouts] を参照してください。

また、[qt "Layout Examples" l=examples-layouts] には上記以外のカスタムレイアウトクラスを作成するサンプルもあります。

レイアウトを使用しよう

それでは 前回 のプログラムをレイアウトを使用するように変更してみましょう。

#include "example.h"
#include <QSlider>
#include <QPushButton>
#include <QVBoxLayout> // [1]

Example::Example(QWidget *parent)
: QWidget(parent)
{
QVBoxLayout *layout = new QVBoxLayout; // [2]
QSlider *slider = new QSlider(Qt::Horizontal);
layout->addWidget(slider); // [3]
QPushButton *button = new QPushButton("Close");
layout->addWidget(button); // [4]
setLayout(layout); // [5]
}

[1] [2] で使用する [qt QVBoxLayout] のヘッダファイルをインクルード

[2] [qt QVBoxLayout] のインスタンス layout を生成

[3] [qt QSlider] のインスタンス slider を layout に登録

[4] [qt QPushButton] のインスタンス button を layout に登録

[5] Example クラスにレイアウトを設定

レイアウト管理の仕組みの中でウィジェットの親子関係も自動的に設定されるため、slider と button 生成時の親ウィジェットの指定は省略しています。上記のコードでは [5] の処理で親ウィジェットの設定がされます。

それでは実行してみましょう。

ウィンドウのサイズを変更しても今度はレイアウトが崩れることはありません。

レイアウトの使用方法について

上記のソースコードでは Qt4 の慣例にしたがい

  1. レイアウトクラスの生成
  2. 子ウィジェットの生成
  3. 子ウィジェットのレイアウトへの登録
  4. 親ウィジェットへのレイアウトの登録

という順番でレイアウトの設定を行いましたが、必ずしもこの順番である必要はありません。

例えば、以下のコードのように親ウィジェットにレイアウトを設定後にさらにウィジェットを追加することも可能です。

    QVBoxLayout *layout = new QVBoxLayout;
QSlider *slider = new QSlider(Qt::Horizontal);
layout->addWidget(slider);
setLayout(layout);

QPushButton *button = new QPushButton("Close");
layout->addWidget(button);

また、layout の生成時に親ウィジェットを設定することで setLayout を省略することも可能です。

    QSlider *slider = new QSlider(Qt::Horizontal);
QPushButton *button = new QPushButton("Close");

QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(slider);
layout->addWidget(button);

おわりに

今回は Qt のレイアウト管理機能について学びました。QVBoxLayout 以外のレイアウトも使用してみてください。

レイアウトにはウィジェットだけではなく [qt QBoxLayout addLayout] や [qt QGridLayout addLayout] などのメソッドを使用して別のレイアウトも登録ができるようになっているため、複数のレイアウトを組み合わせた複雑なユーザーインターフェースの作成が可能になっています。

また、レイアウトの調整は以下のメソッドにて行うことが可能です。

  • [qt QLayout setContentsMargins]
  • [qt QLayout setSpacing]
  • [qt QWidget sizeHint]
  • [qt QWidget setSizePolicy]

次回からは Qt プログラミングの一番のポイントである [qt "シグナル/スロット" l=signalsandslots] について学びましょう。


Blog Topics:

Comments