![]() |
![]() |
Continuous
2009/07/21
ここでは次のような読者を想定している。
なお XMouse にはマウスイベントについての初等的な解説があるので合わせて読むと理解が深まるかも知れない。
XSlider は非常に小さなサンプルプログラムである。Xcode と Interface builder の最初の学習には、このくらいがちょうど良い。

図1. XSlider の実行画面
仕様
この程度の事にプログラムコードを書く必要は無い。
最初に Xcode でプロジェクト XSlider を作る。プロジェクトとしては Cocoa Application を選択する。
Xcode は /Developer/Applications/ に置かれている。開くとチュートリアル "Welcome ..." 画面が現れるが、これは閉じて、「ファイルメニュー」から「新規プロジェクト」を開き、プロジェクト名を付ける。

図2. Xcode の「NIB ファイル」
「NIBファイル」の中の「MainMenu.xib」を開くとウインドウが現れる(図2)。ウインドウに載せるパーツ(オブジェクト)は Interface Builder の Tools → Library から選ぶ。
|
  | ![]() |
| 図3a. スライダーから control-drag でテキストフィールドに繋ぐ |   | 図3b. ドラッグを止めるとメニューが現れるtakeFloatValueFrom: を選ぶ |
オブジェクトを controll-click すると connections panel が現れる*。
|
  | ![]() |
| 図4a. スライダーの connections panel |   | 図4b. テキストフィールドの connections panel |
コンパイルして実行する。
Lesson 2 ではスライダーの変化をプログラムで捉え、その値を読み取り、テキストフィールドに書き出す。
いくつかのステップに分けて作業を進めていく。
Xcode の「ファイル」メニューから「新規ファイル」を開く。(生成するファイルの保存先として「クラス」を指定しておく)

図5. Xcode の「グループとファイル」
「Objective-C NSView subclass」を選択し*、ファイルを保存する。
ファイル名としては、ここでは(簡単な例題なので) XSlide.m とする。すると XSlider.h と XSlider.m が作成される。
Object-C Class ではダメらしい。自動生成された XSlider.h の XSlider クラスにインスタンス変数とメソッドを追加する。インスタンス変数としてはスライダーとテキストフィールドへのポインタ、メソッドはスライダーが変化した時のメッセージを受け取るためのものが必要である。ここでは各々 slider、aField および setfield としている。(もっと適切な名前があったであろう)
#import <Cocoa/Cocoa.h>
@interface XSlider : NSView {
IBOutlet NSSlider *slider;
IBOutlet NSTextField *aField;
}
- (IBAction)setField:(id)sender;
@end
slider.m にメソッド setField の内容を追加する。
#import "XSlider.h"
@implementation XSlider
- (id)initWithFrame:(NSRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code here.
}
return self;
}
- (void)drawRect:(NSRect)rect {
// Drawing code here.
}
- (IBAction)setField:(id)sender
{
float v;
/* set the text field to correspond to the current value of the slider */
//NSRunAlertPanel(@"Message", @"slider changed!", nil, nil, nil);
//if(!slider) NSRunAlertPanel(@"Message", @"slider nil", nil, nil, nil);
v = [slider floatValue];
//NSRunAlertPanel(@"Message",[NSString stringWithFormat:@"%f",v], nil, nil, nil);
//if(!aField) NSRunAlertPanel(@"Message", @"aField nil", nil, nil, nil);
[aField setStringValue:[NSString stringWithFormat:@"%f",v]];
}
@end
デバッグのためのコードが含まれているが、役に立つかも知れない。
コンパイルする
XSlider を実行し、スライダーのノブを移動した時にメッセージが setfield に届く事を確認する。実はここが(初心者の僕にとって)最も難しい課題であった。僕はソースコードと Interface Builder で表示されるオブジェクトの関係がなかなか分からなかったのである。
alert panel はこのような場合のデバッグに便利である。setfield の中の最初の NSRunAlertPanel のコメントを外しておけば、メッセージが届いた時に
slider changed!
のメッセージが表示されるはずである。
Interface Builder はソースコードをどのようにしてビジュアルに表示されているオブジェクトと結び付けているのか?
ウインドウのパネル(トップバーではない!)を選択してインスペクターを覗くと Class が表示される(下図)。この内容をソースコードの中の Class 名に変更する。図のボタン ▼ をクリックすれば一覧の中に XSlider が見えるはずである。XSlider を選べば Class Actions と Class Outlets の中に、ソースコードの中で指定された内容が表示される。

図6. ウインドウパネルのインスペクタ情報
なお、インスペクターのトップバーが Slider Identity となっているが、この Slider は XSlider から X を除去した文字列である。
ソースコードの中の slider の値はこのままでは NULL である。これに実体(メモリ)を割り当てなくてはならない。この作業はソースコードの中の slider がウインドウの中のスライダーである事を教える事によって初期化時に自動的に行われるはずである。
ウインドウのパネル(トップバーではない!)を control-click して connections panel を表示させる。すると Outlets の中に slider が表示されるので、これをウインドウの中のスライダーにドラッグする。(下図)

図7. コード中の slider を実体と結びつける
ついでに、aField も同様な方法でウインドウのテキストフィールドと結びつけておく。(上の図では結びつけられた結果が表示されている)
スライダーのノブを移動した時に、setField にメッセージが届かなくてはならない。First Responder の connections panel を開くと setField:が含まれている。スライダーにドラッグする。(下図)

図8. スライダのアクションの先を指定する
注: 実は setField: はウインドウ(Slider)の connections panel の中にも存在する。どちらの setField: をスライダーと結びつけても実行結果に違いは見当たらない。僕には今のところ、使い方の違いを知らない。2つの setField を同時にはスライダーに結びつける事はできない。
以上で正しく実行されるはずである。
旨く行かない時には実装コードのコメントを外してみる。どこで問題が発生しているかが分かるはずである。
デバッグに、データの値を表示するコードを含めるのは初等的ではあるが、基本的でもある。ただ NSRunAlertPanel は大袈裟だし、使い辛い。もっと手軽で、強力な方法は、C の標準出力関数である printf() を利用する事である。そのためには XSlider.h の中に
#import <stdio.h>
を含める。さらに、標準出力が見えるようにコマンドラインで実行する。そのためには...

図9. XSlider.app の場所
control-click で「パッケージの内容を表示」を選ぶ。

図10. XSlider.app の中の XSlider
この XSlider をコマンドラインから実行すれば printf() の出力が見える。さらに実行時のエラーも表示される事がある。
Continuous2009/07/23
デフォルトのスライダーの設定では、ノブを離した時にしか変化を伝えられない。この設定は通常は都合が悪いであろう。ノブ位置の変化をリアルタイムでアプリケーションに伝達するにはスライダーのアトリビュートで "Continuous" にチェックマークを付ける。

図11. スライダーのアトリビュート
2009/07/23
View クラスとは平たく言えば見えるもののクラスだと考えてよい*。それらは大きさや位置を表す共通の内部変数を持っている。Cocoa における View クラスの実装である NSView クラスでは見えるものは矩形(rectangle)で囲まれており、これを frame と呼んでいる。NSView クラスのインスタンスは全て frame 情報を返す frame メソッドを持っている。frame と良く似たものに bounds がある。この違いに関しては以下の文献 "View Geometry" に詳しい。