Qt をはじめよう! 第13回: GUI デザイナを使おう

前回は独自のシグナルとスロットを作成し使用してみました。

これまでのサンプルではアプリケーションのユーザーインターフェースのデザインを C++ のコードで作成してきました。

今回はユーザーインターフェースを GUI のツールを用いてデザインする方法について解説します。

第5回: Qt Creator を使ってみよう!」、「第6回: 簡単なブラウザを作ってみよう!」 で既に使用したとおり、Qt では UI を GUI のツールでデザインすることが可能です。「第8回: QWidget の親子関係を学ぼう」、「第9回: レイアウト管理を学ぼう」 では、ソースコードでウィジェットの生成やレイアウトの管理をしましたが、これは GUI ツールを使用して UI のデザインをする際の背景となる仕組みを理解するためでした。

今回は前回まで使用したサンプルではなく、新しくプロジェクトを作成します。

プロジェクトの作成

「ファイル(F)」 -> 「ファイル/プロジェクトの新規作成(N)...」 を選択してください。

プロジェクト中から「Qt C++ プロジェクト」を選択し、「Qt GUI アプリケーション」を選択して「選択(C)...」をクリックしてください。

名前を「example2」と変更し「次へ(N)>」をクリックしてください。

使用する Qt のバージョンを選択し、「次へ(N)>」をクリックしてください。

クラス名:Example

基底クラス:QWidget

とします。今回は GUI で UI のデザインを作成するため、「フォームを生成する(G)」のチェックはつけたままにしてください。

「完了(F)」をクリックするとアプリケーションのテンプレートが生成され、以下の画面が表示されます。

作成されたプロジェクトの確認

フォームをデザインする前に、作成されたプロジェクトの確認をしましょう。

サイドバーの「編集」ボタンをクリックしてソース画面に切り替えてください。

プロジェクトに「フォーム」というカテゴリが追加され、「example.ui」というファイルが生成されています。このファイルが Qt でウィジェットのデザインをするためのフォームとなります。ファイルの中身は右ペインに表示されているとおり XML の形式になっています。また、プロジェクトファイル「example2.pro」を開くと

FORMS += example.ui

というエントリが生成されていますので確認してみてください。

フォームのデザイン

それでは「デザイン」ボタンを押してデザイン画面に戻りましょう。

この画面が .ui ファイルを GUI で編集するツールになります。Qt と一緒に提供されている「Qt デザイナ」というツールを Qt Creator に統合したものになります。

左側にはウィジェットの一覧が表示されています。フォームにウィジェットを配置する際はここからドラッグ&ドロップします。

中央の下はアクションの一覧とシグナル/スロットの接続の一覧です。

右上はオブジェクトの一覧で、QWidget の親子関係を反映したツリーとして表示されます。

右下はプロパティの一覧で、選択されているオブジェクトのプロパティの一覧が表示され、変更ができるようになっています。

ここでフォームのオブジェクト名(objectNameプロパティの値)が「Example」となっている事に注目してください。このオブジェクト名がこのファイルから後ほど生成されるクラスのクラス名になります。

それではウィジェットを配置していきましょう。

左側のウィジェットリストから「Horizontal Slider」をドラッグし、フォーム上にドロップしてください。このとき左上のフィルタフォームに「sl(ider)」と入力することで素早く目的のウィジェットを見つけることができるでしょう。

同様に、「Push Button」をスライダの下にドラッグ&ドロップして配置してください。この時も「but(ton)」でフィルタすると探しやすいでしょう。

次にこのボタンの文字を変更します。ボタンを右クリックして「テキストを変更...」を選択し、「Close」に変更してください。

ボタンの文字の変更はプロパティエディタの text プロパティの変更や、ボタンをダブルクリックする事でも可能です。

次はレイアウトを設定します。Example ウィジェットに対してレイアウトを設定するため、Example(フォーム自体)を選択した状態で画面上部の「垂直に並べる(V)」ボタンをクリックしてください。

フォームの右クリックからも同様の操作が可能です。

以上で子ウィジェットの配置とレイアウトの設定は完了です。

最後に画面が間延びしているのでサイズを調整しましょう。

画面上部の「サイズ調整(S)」というボタンを押すと、個々のウィジェットの理想的なサイズを考慮した最適なサイズにリサイズされます。

各ウィジェットのオブジェクト名の変更

画面右上のオブジェクトインスペクタ内の各オブジェクト名をダブルクリックし、スライダのオブジェクト名を「slider」に、ボタンのオブジェクト名を「button」に変更してください。

オブジェクト名の変更はフォーム上のウィジェットの右クリックで表示されるコンテキストメニューの「オブジェクト名を変更...」や、画面右下のプロパティエディタの「objectName」の変更でも可能です。

ここで変更したオブジェクト名はフォームから生成されるクラスのメンバ変数名となり、ソースコードから各ウィジェットにアクセスする際に使用します。

フォームのプレビュー

ツール(T) -> フォーム エディタ(M) -> Preview... を選択すると現在のフォームのプレビューが見られます。

フォームを使用する

作成したフォームはコンパイル時に uic というツールによって C++ のヘッダファイルに変換されます。この時、example.ui というファイルからは ui_example.h というファイルが生成されます。この中には Ui という名前空間の中にフォームのオブジェクト名と同じ名前のクラスが定義され、子ウィジェットはそれぞれのオブジェクト名を名前とするメンバ変数として定義されます。ソースコードでフォームを使用する場合はこのクラスのインスタンスを生成し、setupUi(QWidget *parent)メソッドを呼び出します。

Qt Creator でアプリケーションを「フォームを生成する」をチェックして生成した場合には、以下のように既にこのコードが記述された状態になっています。

example.h

namespace Ui {
class Example; // [1]
}

class Example : public QWidget
{
...
private:
Ui::Example *ui; // [2]
};

example.cpp

#include "example.h"
#include "ui_example.h" // [3]

Example::Example(QWidget *parent) :
QWidget(parent),
ui(new Ui::Example) // [4]
{
ui->setupUi(this); // [5]
}

Example::~Example()
{
delete ui; // [6]
}

[1] Ui::Example クラスの宣言です

[2] Ui::Example クラスのポインタを private なメンバ変数として保持します

[3] ui_example.h をインクルードします

[4] Ui::Example クラスを生成しています

[5] Ui::Example クラスの setupUi メソッドを実行しています

[6] [4] で生成した ui を破棄しています

setupUi() を実行した際に、引数に渡されたウィジェットに対して親ウィジェットのプロパティの変更や子ウィジェットの生成など、フォームの内容が適用されます。

ビルドと実行

それではビルドをして実行してみてください。

コンパイル時のログを確認して uic というツールによって example.ui から ui_example.h が生成されていることを確認してみてください。

/home/tasuku/qtsdk-2010.04/qt/bin/uic ../example2/example.ui -o ui_example.h

また、ビルドディレクトリに生成されている ui_example.h を開き、クラスがどのように定義されているか、setupUi メソッドの中の処理がどうなっているかも確認してみてください。基本的な処理は「第8回: QWidget の親子関係を学ぼう」、「第9回: レイアウト管理を学ぼう」で記述した内容と同じになっています。

ボタンを押した際に閉じるようにする

最後に「Close」ボタンを押した際にウィンドウを閉じてアプリケーションが終了するようにしましょう。

Example::Example(QWidget *parent) :
QWidget(parent),
ui(new Ui::Example)
{
ui->setupUi(this);
connect(ui->button, SIGNAL(clicked()), this, SLOT(close())); // [1]
}

[1] 「ui」 のボタン「button」の [qt "" clicked l=qabstractbutton] シグナルを Example クラスの [qt "" close l=qwidget] スロットに接続

この接続は「第10回: シグナルとスロット」で行なったものと一緒です。ボタンのインスタンスがフォーム Ui::Example の button というメンバ変数に変わっています。

フォームを使う際のまとめ

  1. Qt では .ui という拡張子のファイルを使用してフォームをデザインする
  2. プロジェクトファイルの FORM エントリに使用するフォームを追加する
  3. example.ui という ui ファイルから ui_example.h というヘッダファイルが生成される
  4. Ui という名前空間にフォームのオブジェクト名と同じ名前のクラスが定義される
  5. 子ウィジェット(とレイアウト)はオブジェクト名と同じ名前のメンバ変数として定義される
  6. フォームを使用する際は生成されたクラスの setupUi メソッドを呼ぶ

おわりに

Qt では GUI のツールを使用することにより UI の作成が簡単にできることがお分かりいただけたでしょうか。今回のようなシンプルな UI の場合はソースコードで書いても手間は変わりませんが、UI が複雑になるにつれソースコードでの生成や変更にかかる手間は多くなるため、ツールを使用して作成するメリットは大きくなるでしょう。

次回はさらに複雑な UI のデザインやツールを用いたシグナル/スロットの接続などを学びましょう。


Blog Topics:

Comments