ビューを言葉で説明すると、ウィンドウ内の描画全般と
ユーザーとの対話を受け持つ部門であると言えます。
今回のプログラムでは文字を描画していますが、
BViewの描画機能として(カッコ内はメンバ関数名)
が挙げられます。また、ユーザーとの対話機能として、
があります。今回は文字描画のみですが、基本的な使い方はわかると思います。
今回のサンプルソースです。
前回同様、重要な部分は強調してあります。
// sample03.cpp
#include <Application.h> // BApplicationを使うために必要
#include <Window.h> // BWindowを使うために必要
#include <Rect.h> // BRectを使うために必要
#include <View.h> // BViewを使うために必要
// クラスの前方宣言
class MyApp;
class MyWindow;
class MyView;
class MyApp : public BApplication
{
public:
MyApp();
private:
MyWindow* m_win;
};
class MyWindow : public BWindow
{
public:
MyWindow(BRect frame,const char* title,window_type type,uint32 flags);
virtual bool QuitRequested(); // 終了が要求されたときに呼ばれる関数
private:
MyView* m_view;
};
class MyView : public BView
{
public:
MyView(BRect frame,const char *name,uint32 resizingMode,uint32 flags);
virtual void Draw(BRect updateRect); // 再描画要求の時に呼ばれる関数
};
MyApp::MyApp()
:BApplication("application/x-vnd.big56-MyApp")
{
m_win = new MyWindow(BRect(100,100,300,150),"BViewのテスト",B_DOCUMENT_WINDOW,0);
m_win->Show();
}
MyWindow::MyWindow(BRect frame,const char* title,window_type type,uint32 flags)
:BWindow(frame,title,type,flags)
{
frame.OffsetTo(0,0); // 与えられたBRectの左上が(0,0)になるようにする
m_view = new MyView(frame,"theView",B_FOLLOW_NONE,B_WILL_DRAW);
AddChild(m_view);
}
bool MyWindow::QuitRequested()
{
// アプリケーションを終了する
be_app->PostMessage(B_QUIT_REQUESTED);
return true;
}
MyView::MyView(BRect frame,const char* title,uint32 resizingMode,uint32 flags)
:BView(frame,title,resizingMode,flags)
{
SetViewColor(200,200,200); // ビューの背景色を設定する
SetFontSize(20); // フォントサイズを設定する
}
void MyView::Draw(BRect updateRect)
{
MovePenTo(20,20);
DrawString("Hello BView!");
}
int main(int argc,char** argv)
{
MyApp app;
app.Run();
return 0;
}
今回のプログラムの実行結果は次のようになります。
MyWindowのコンストラクタから見てみましょう。
MyWindow::MyWindow(BRect frame,const char* title,window_type type,uint32 flags)
:BWindow(frame,title,type,flags)
{
frame.OffsetTo(0,0); // 与えられたBRectの左上が(0,0)になるようにする
m_view = new MyView(frame,"theView",B_FOLLOW_NONE,B_WILL_DRAW);
AddChild(m_view);
}
まず、frame.OffsetTo(0,0);ですが、これは、BRectの矩形の座標を大きさを変えずに左上を(0,0)にスライドしています。
今回は、ウィンドウの座標を(100,100,300,150)に指定していますが、
この操作をすると、(0,0,200,50)という矩形の座標になります。
なぜこのようなことをするかというと、ビューの占める面積をウィンドウ全体にしたいからです。
ビューを作成するときに、デスクトップの座標ではなく、ウィンドウ内の座標で指定する必要があるため
矩形の左上の点を(0,0)にしているのです。
次にビューのインスタンスをnewで作成して、AddChild()関数でビューをウィンドウの子供として登録します。
ウィンドウとビューの関係、またはビューとビューの関係はフォルダ階層に似ています。
ウィンドウはルートディレクトリ(ドライブのいちばん上のこと)、ビューはフォルダと考えてください。
「子供として登録する」とは、フォルダを掘るのに似ています。
ウィンドウが複数のビュー(ルートディレクトリに複数のフォルダがある)を持ったり、
ウィンドウの子供のビューが、さらに子供にビューを持つ(フォルダの下にさらにフォルダを掘る)こともあります。
「ビューを複数持つことに意味があるのか?」と考える人もいると思いますが、
今後紹介する、ウィンドウのボタン(BButtonクラス)とかチェックボックス(BCheckBoxクラス)は
すべてビューの一部です(BViewクラスから派生している)。
ウィンドウが複数のボタンや複数のチェックボックスを持つ必要があるときに
AddChild()メンバ関数を複数呼んで、ウィンドウは子供のビューを複数持つことになります。
さて、BViewのコンストラクタについての説明をします。
MyView::MyView(BRect frame,const char* title,uint32 resizingMode,uint32 flags)
:BView(frame,title,resizingMode,flags)
{
SetViewColor(200,200,200); // ビューの背景色を設定する
SetFontSize(20); // フォントサイズを設定する
}
BViewのもともとのコンストラクタの引数並びは次のようになっています。
BView(BRect frame,const char* name,uint32 resizingMode,uint32 flags);
BViewでは
ビューの名前は直接表示されることはありませんが、プログラム的にビューを識別するのに使います。
今回はビューの名前を利用していません。
resizingModeには次の定数を指定することが出来ます。
| B_FOLLOW_LEFT | 左に追従する |
| B_FOLLOW_RIGHT | 右に追従する |
| B_FOLLOW_LEFT_RIGHT | 水平方向は親に合わせて子供もリサイズする |
| B_FOLLOW_H_CENTER | 左と右の中心の位置を保つ |
| B_FOLLOW_TOP | 上に追従する |
| B_FOLLOW_BOTTOM | 下に追従する |
| B_FOLLOW_TOP_BOTTOM | 垂直方向は親に合わせて子供もリサイズする |
| B_FOLLOW_V_CENTER | 上と下の中心の位置を保つ |
| B_FOLLOW_ALL_SIDES | B_FOLOW_LEFT_RIGHTとB_FOLLOW_TOP_BOTTOMをあわせたもの |
| B_FOLLOW_NONE | どこにも移動しない |
flagsには次の定数を指定できます。
| B_WILL_DRAW | ビューが再描画要求の通知を受け取れるようにする。 |
| B_PULSE_NEEDED | ビューのPulse()メンバ関数を定期的に呼ぶ。 |
| B_FRAME_EVENTS | BViewがリサイズされるときに、FrameResized()メンバ関数と FrameMoved()メンバ関数を呼び出す |
| B_FULL_UPDATE_ON_RESIZE | リサイズの時にビュー全体を更新する必要があることを 表すフラグ |
| B_NAVIGATABLE | キーボード入力のフォーカスビューになりえることを表すフラグ |
| B_NAVIGATABLE_JUMP | Ctrl+Tabキーを押すとビューのグループからビューのグループへジャンプできる。 |
| B_SUBPIXEL_PRECISE | 描画の際にサブピクセル精度を使用するように指示するフラグ。 これを指示しないと、1座標単位に丸められる。 |
ということらしいです(実は筆者も全部ためしていない)。
その次のSetViewColorメンバ関数でビュー全体の色を設定します。
SetViewColor()関数の宣言は次のようになっています。
void BView::SetViewColor(rgb_color color); void BView::SetViewColor(uchar red,uchar green,uchar blue,uchar alpha=0);
rgb_color構造体は、パラメータにredとgreenとblueとalphaという変数名を持つ単純な構造体です。
rgb_color構造体を使用しないほうのSetViewColor関数では、
第1引数に赤成分、第2引数に緑成分、第3引数に青成分、第4引数にアルファ成分(透明度)を指定することによって、
ビューの色を指定します。
SetFontSizeでは描画に使用するフォントの大きさを指定します。
ここの引数を変えると「Hello BView!」の大きさも変化します。
さて、再描画要求にはDrawメンバ関数内で応じるわけですが、この部分のコードの解説をしましょう。
void MyView::Draw(BRect updateRect)
{
MovePenTo(20,20);
DrawString("Hello BView!");
}
Draw()メンバ関数の引数には、更新すべき領域の矩形が渡されます。
多くの領域を描画するようなアプリケーションなら、この部分の矩形領域を利用して
必要な所だけ描画するようにするべきでしょうが、今回はこの引数を無視してビュー全体を更新しています。
DrawString()メンバ関数で実際に文字を書いていますが、DrawStringの書き始めの位置は「ペン」と呼ばれるものの座標から始まります。
ペンの座標はMovePenTo()で指定します。
MovePenTo()関数は以下のように宣言されています。
void BView::MovePenTo(BPoint point); void BView::MovePenTo(float x,float y);BPointクラスは座標を表すクラスですが、今回は簡単にするために、x座標とy座標を指定するタイプの方を使用しています。
Draw()関数以外の部分でDrawStringをすると、ほかのウィンドウをかぶせた時に
「Hello BView!」の文字が消えてしまいます。
これは、再描画の必要があるのに文字を描画していないからです。
ビューに対して描画するには、Draw()関数内で描画するのが定石です。
今回のソースについての説明は以上ですが、いかがでしたでしょうか?
ビューはBeOSプログラムにおいて非常に重要な概念なので、きっちり押さえるようにしてください。