address Logo

XSlider: A Simple Sample Using Slider

目次

2009/07/21

ここでは次のような読者を想定している。

なお XMouse にはマウスイベントについての初等的な解説があるので合わせて読むと理解が深まるかも知れない。

環境

目標

XSlider は非常に小さなサンプルプログラムである。Xcode と Interface builder の最初の学習には、このくらいがちょうど良い。

XSlider-1

図1. XSlider の実行画面

仕様

Lesson 1

準備

この程度の事にプログラムコードを書く必要は無い。

最初に Xcode でプロジェクト XSlider を作る。プロジェクトとしては Cocoa Application を選択する。


Xcode は /Developer/Applications/ に置かれている。開くとチュートリアル "Welcome ..." 画面が現れるが、これは閉じて、「ファイルメニュー」から「新規プロジェクト」を開き、プロジェクト名を付ける。


nib

図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
注*: オブジェクトを選択して、Tools -> Inspector -> Panel Connections を辿っても同等な情報が得られる。むしろこの方が普通の方法かも知れない。

実行

コンパイルして実行する。

Lesson 2

Lesson 2 ではスライダーの変化をプログラムで捉え、その値を読み取り、テキストフィールドに書き出す。

いくつかのステップに分けて作業を進めていく。

STEP 1: クラスファイルの作成

Xcode の「ファイル」メニューから「新規ファイル」を開く。(生成するファイルの保存先として「クラス」を指定しておく)

fig0

図5. Xcode の「グループとファイル」

「Objective-C NSView subclass」を選択し*、ファイルを保存する。

ファイル名としては、ここでは(簡単な例題なので) XSlide.m とする。すると XSlider.hXSlider.m が作成される。

注*: どうやら Object-C Class ではダメらしい。

自動生成された XSlider.hXSlider クラスにインスタンス変数とメソッドを追加する。インスタンス変数としてはスライダーとテキストフィールドへのポインタ、メソッドはスライダーが変化した時のメッセージを受け取るためのものが必要である。ここでは各々 slideraField および 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

デバッグのためのコードが含まれているが、役に立つかも知れない。

STEP 2

コンパイルする

STEP 3

目標

XSlider を実行し、スライダーのノブを移動した時にメッセージが setfield に届く事を確認する。実はここが(初心者の僕にとって)最も難しい課題であった。僕はソースコードと Interface Builder で表示されるオブジェクトの関係がなかなか分からなかったのである。

alert panel はこのような場合のデバッグに便利である。setfield の中の最初の NSRunAlertPanel のコメントを外しておけば、メッセージが届いた時に

    slider changed!

のメッセージが表示されるはずである。

行うべき事


Interface Builder はソースコードをどのようにしてビジュアルに表示されているオブジェクトと結び付けているのか?

ウインドウのパネル(トップバーではない!)を選択してインスペクターを覗くと Class が表示される(下図)。この内容をソースコードの中の Class 名に変更する。図のボタン ▼ をクリックすれば一覧の中に XSlider が見えるはずである。XSlider を選べば Class Actions と Class Outlets の中に、ソースコードの中で指定された内容が表示される。

fig1

図6. ウインドウパネルのインスペクタ情報

なお、インスペクターのトップバーが Slider Identity となっているが、この SliderXSlider から X を除去した文字列である。

STEP 4

ソースコードの中の slider の値はこのままでは NULL である。これに実体(メモリ)を割り当てなくてはならない。この作業はソースコードの中の slider がウインドウの中のスライダーである事を教える事によって初期化時に自動的に行われるはずである。

ウインドウのパネル(トップバーではない!)を control-click して connections panel を表示させる。すると Outlets の中に slider が表示されるので、これをウインドウの中のスライダーにドラッグする。(下図)

fig2

図7. コード中の slider を実体と結びつける

ついでに、aField も同様な方法でウインドウのテキストフィールドと結びつけておく。(上の図では結びつけられた結果が表示されている)

STEP 5

スライダーのノブを移動した時に、setField にメッセージが届かなくてはならない。First Responder の connections panel を開くと setField:が含まれている。スライダーにドラッグする。(下図)

fig3

図8. スライダのアクションの先を指定する

注: 実は setField: はウインドウ(Slider)の connections panel の中にも存在する。どちらの setField: をスライダーと結びつけても実行結果に違いは見当たらない。僕には今のところ、使い方の違いを知らない。2つの setField を同時にはスライダーに結びつける事はできない。

実行

以上で正しく実行されるはずである。
旨く行かない時には実装コードのコメントを外してみる。どこで問題が発生しているかが分かるはずである。

デバッグ

デバッグに、データの値を表示するコードを含めるのは初等的ではあるが、基本的でもある。ただ NSRunAlertPanel は大袈裟だし、使い辛い。もっと手軽で、強力な方法は、C の標準出力関数である printf() を利用する事である。そのためには XSlider.h の中に

    #import <stdio.h>

を含める。さらに、標準出力が見えるようにコマンドラインで実行する。そのためには...

fig4

図9. XSlider.app の場所

control-click で「パッケージの内容を表示」を選ぶ。

fig5

図10. XSlider.app の中の XSlider

この XSlider をコマンドラインから実行すれば printf() の出力が見える。さらに実行時のエラーも表示される事がある。

ソースコード

XSlider.zip

Tips

スライダーの属性: Continuous

2009/07/23

デフォルトのスライダーの設定では、ノブを離した時にしか変化を伝えられない。この設定は通常は都合が悪いであろう。ノブ位置の変化をリアルタイムでアプリケーションに伝達するにはスライダーのアトリビュートで "Continuous" にチェックマークを付ける。

slider-attr

図11. スライダーのアトリビュート

View クラス

2009/07/23

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

注*: 正確に言えば、見えるもののクラスには他に Window がある。Menu クラスは「目に見える」とも言えなくもないが、独自のクラスを形成する。