はじめに
前回は,Qtの中核機能からシグナルとスロットというタイプセーフなコールバックについて説明しました。今回は,シグナルとスロットの実装の基礎となっているQtのオブジェクトモデルについて説明します。
オブジェクトモデル
Qtのオブジェクトモデルでは,C++オブジェクトにシグナルとスロットを含む表1の機能拡張をして,GUIプログラミングに必要とされる柔軟性を高めています。
表1 オブジェクトモデルで拡張された機能
| シグナルとスロット | タイプセーフコールバック,オブジェクトの疎結合とカプセル化 |
|---|---|
| オブジェクトプロパティ | 問い合わせ可能なプロパティ |
| イベントとイベントフィルター | イベント処理とイベントフック |
| 国際化用テキスト文字列の翻訳 | クラスをコンテキストとするテキスト文字列翻訳 |
| インターバルタイマー | イベント処理と統合されたタイマー |
| オブジェクトツリー | オブジェクトの階層化と検索 |
| ガーディドポインター | QPointer。Qt 4.5でQSharedPointerとQWeakPointerが追加 |
| ダイナミックキャスト | ライブラリ境界制限のないダイナミックキャスト |
これらの機能は,オブジェクトクラスQObjectに対して実装されています。この中からオブジェクトプロパティ,オブジェクトツリー,ダイナミックキャストの3つ,それとこれらを支えているメタオブジェクトシステムについて説明します。
オブジェクトツリー
図1のように,既存のウィジェットをウィジェットの上に配置して作成するウィジェットをコンポジットウィジェットと呼び,以下の5つがその実装上のポイントです。
- ウィジエットがどのウィジェット上に置かれているか
- ウィジェットをどのように並べるか
- ウィジェットの表示/非表示の制御
- ウィジェットの有効化/無効化の制御
- ウィジェットのメモリ割り当てと解放の制御
Qtでは,これらの機能の実装にオブジェクトツリーが利用されています。2番目の「ウィジェットの並べ方」は,次回に詳しく説明します。
図1のコンポジットウィジェットのオブジェクトツリーは,レイアウトのためのオブジェクトを省略して,ウィジェットのみに着目すると,図2のようになります。
QFrameとQGroupBoxの親オブジェクトはQWidget,QLabelとQSliderの親オブジェクトはQGroupBoxです。QFrameの親クラスはQWidgetですが,QLabelやQSliderの親クラスはQGroupBoxでないことからわかるように,クラスの継承関係とは異なることに注意しましょう。これらのオブジェクトの親子関係はQObjectの機能で,QObjectを継承したQWidgetでは,この親子関係が,ウィジェットがどのウィジェットの上に乗っているかというウィジェットの上下関係に対応付けられています。
ウィジェットの親子関係に着目したコードはリスト1のようになります。
リスト1 ウィジェットの親子関係
class ColorChooser : public QWidget
{
...
private:
QFrame* colorFrame;
QSlider* redSlider;
QSlider* greenSlider;
QSlider* blueSlider;
}
ColorChooser::ColorChooser( QWidget* parent )
: QWidget( parent )
{
...
colorFrame = new QFrame(this);
QGroupBox* colorGroupBox = new QGroupBox("RGB", this);
QLabel* redLabel = new QLabel("&Red", groupBox);
QLabel* greenLabel = new QLabel("&Green", groupBox);
QLabel* blueLabel = new QLabel("&Blue", groupBox);
redSlider = new QSlider(Qt::Horizontal, colorGroupBox);
greenSlider = new QSlider(Qt::Horizontal, colorGroupBox);
blueSlider = new QSlider(Qt::Horizontal, colorGroupBox);
...
}
ColorChooser::~ColorChooser()
{
// 子ウィジェットのメモリ解放は不要。
}
ウィジェットのインスタンス生成時に親ウィジェットを指定しているのがポイントです。QObject またはその継承クラスのインスタンス生成では,親オブジェクトを指定して,オブジェクトツリーを形成できるようにしています。親オブジェクトは子オブジェクトのリストを持っていて,子オブジェクトは親オブジェクトを指すポインタを持っています。ウィジェットに親子関係を付けることによって,以下のことが可能となっています。



