Qt をはじめよう! 第8回: QWidget の親子関係を学ぼう

前回は [qt QObject] の親子関係について学びました。今回は [qt QWidget] についてです。

QWidget

[qt QWidget] は [qt QObject] のサブクラスで、Qt の全てのウィジェットの基底クラスです。

ウィジェットとは GUI を構成する各要素のことをいいます。ラベルやボタン、ウィンドウそのもの等です。

[qt QWidget] は以下のようなウィジェットとしての基本的な機能を提供します。

  • [qt "" "位置(pos)" l=qwidget m=#pos-prop]、[qt "" "大きさ(size)" l=qwidget m=#size-prop]
  • [qt "" "フォント(font)" l=qwidget m=#font-prop]、[qt "" "パレット(palette)" l=qwidget m=#palette-prop]
  • [qt "" "カーソル(cursor)" l=qwidget m=#cursor-prop]、[qt "" "フォーカス(focus)" l=qwidget m=#focus-prop]
  • [qt "" "表示/非表示(visible)" l=qwidget m=#visible-prop]、[qt "" "有効/無効(enabled)" l=qwidget m=#enabled-prop]
  • 描画機能
  • マウスやキーボード等のイベントハンドラ

QWidget の親子関係

それぞれの QWidget は親ウィジェットを持つことができ、以下の API より設定できます。

  • [qt "" "QWidget::QWidget(QWidget *parent, ...)" l=qwidget m=#QWidget] // コンストラクタ
  • [qt "" "void QWidget::setParent(QWidget *parent)" l=qwidget m=#setParent] // 設定メソッド

QWidget は QObject を継承しているため、QObject の親子関係がそのまま成り立ちます。QWidget ではそれに加えて以下のウィジェットとしての親子関係が成立します。

  • 子ウィジェットの位置は親ウィジェットに対する相対的な位置になる
  • 子ウィジェットは、親ウィジェットの範囲内に描画される
  • 子ウィジェットでは(明示的な指定がない場合) visible, enabled, palette, font 等のプロパティは親ウィジェットから引き継がれ、親ウィジェットのこれらのプロパティが変更された場合には子ウィジェットにも伝搬する

また、親ウィジェットを持たないウィジェットは ウィンドウ となり、最小化/最大化等ののボタンを含むタイトルバーやウィンドウの枠が表示され、各プラットフォームのウィンドウマネージャーによって管理されます。
それでは以下のアプリケーションのプログラムを書きながら実際の動きを確認してみましょう。

新しいプロジェクトの作成

ファイル(F) -> ファイル/プロジェクトの新規作成(N)… を選択してください。
今回も「Qt4 GUI アプリケーション」を選択します。

プロジェクト名とパス

example という名前のアプリケーションを作成します。

必須モジュールの選択

今回は QtCore と QtGui モジュールのみを使用します。そのまま次へをクリックしてください。

クラス情報

クラス名:Example と入力

基底クラス:QWidget を選択

フォームを生成する:チェックを外す

として、次へをクリックしてください。

今回は UI をソースコードで生成するため、フォームは使用しません。

プロジェクト管理


完了をクリックするとアプリケーションのテンプレートが生成されます。

子ウィジェットの生成とジオメトリ(位置、大きさ)の設定

[qt QSlider] と [qt QPushButton] を上下に並べて配置します。

example.cpp を開き以下のように編集してください。

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

Example::Example(QWidget *parent)
: QWidget(parent)
{
QSlider *slider = new QSlider(Qt::Horizontal, this); // [3]
slider->setGeometry(10, 10, 200, 20); // [4]
QPushButton *button = new QPushButton("Close", this); // [5]
button->setGeometry(10, 40, 200, 30); // [6]
}

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

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

[3] 親ウィジェットに this(Example) を指定し水平方向の [qt QSlider] のインスタンス slider を生成

[4] slider のジオメトリの設定

[5] 親ウィジェットに this(Example) を指定し "Close" というテキストの [qt QPushButton] のインスタンス button を生成

[6] button のジオメトリの設定


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

Example クラスのコンストラクタで生成した2つのウィジェットが Example の子ウィジェットとして表示されています。スライダを動かしたりボタンを押したりすることは可能ですが、動作は実装していないため何も起こりません。

Example::~Example()
{

}

Example クラスのデストラクタでは何もしていない点に着目してください。

Example を親オブジェクトとして指定して生成した slider, button は、Example のインスタンスが delete される際に自動で delete されるためここで delete をする必要はありません。(delete しても問題はありません。)

main.cpp

main.cpp を開き、ソースコードを見てみましょう。

下記の内容は典型的な Qt のアプリケーションにおける main.cpp のコードになります。

#include <QtGui/QApplication> // [1]
#include "example.h" // [2]

int main(int argc, char *argv[])
{
QApplication a(argc, argv); // [3]
Example w; // [4]
w.show(); // [5]
return a.exec(); // [6]
}

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

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

[3] [qt QApplication] のインスタンス a を生成

[4] Example のインスタンス w を生成

[5] w を表示

[6] a を実行し、Qt のイベントループに入る

[4] で Example のインスタンス w を生成した際に親ウィジェットを指定していないことに着目してください。w は親ウィジェットを持たないウィジェットとなり、ウインドウとして扱われます。

おわりに

今回は QWidget の親子関係について学びました。

プログラミングでは [qt QWidget] のサブクラスを作成し、その中で子ウィジェットを生成して表示しました。

今回は子ウィジェットの位置や大きさを固定値で指定したため、ウィンドウのサイズを変更した場合には見た目がおかしくなってしまいます。

次回はこの問題を解決する[qt "レイアウト" l=layout]という仕組みについて学びましょう。


Blog Topics:

Comments