XMouse.h
XMouse.m
XMouse.h
XMouse.m
2009/07/22
2009/08/04 追加
ここでは次のような読者を想定している。
なお XSlider から "A Simple Sample ..." が始まっているので、Xcode の起動の仕方が分からなければ XSlider から読んで欲しい。
ウインドウの中のボックス領域でマウス操作が発生した時のマウスイベントを捉える。
マウスイベントとしてはいろいろあるが(mouseDown
, mouseUp
, mouseDragged
など)最初に mouseDown
から始める。
マウスをクリックしたときの座標をテキストフィールドに書き出す。(下図)
新規プロジェクトで Cocoa Application を選び、プロジェクト名を XMoude
とする。新規ファイルで NSView subclass
を選び、ファイル名を XMouse.m
とする。この時 XMouse.m
の他に XMouse.h
も生成される。
XMouse.h
#import <Cocoa/Cocoa.h> //#import <stdio.h> @interface XMouse : NSView { IBOutlet NSTextField *messageTextField; IBOutlet NSBox *box; } - (void)mouseDown:(NSEvent *)event; //Kenar @end
この中のコメントアウトされている行
//#import <stdio.h>
はデバッグで使われていた行である。
マウスをクリックする領域(box)、クリックした座標を表示するテキストフィールド(messageTextField)およびマウスクリック(mouseDown
を捉えるメソッドが宣言されている。
XMouse.m
#import "XMouse.h" @implementation XMouse - (void)mouseDown:(NSEvent *)event //Kenar { // mouse-down event comes here. NSString *s; NSPoint p = [event locationInWindow]; NSRect r; s = [NSString stringWithFormat:@"(%f,%f)", p.x,p.y]; //NSRunAlertPanel(@"Message", (NSString *)s, NULL, NULL, NULL); //if(!box) NSRunAlertPanel(@"Warning", @"box nil", NULL, NULL, NULL); r = [box frame];// frame is a generic method for NSView class. //printf("%f,%f,%f,%f\n",r.origin.x,r.origin.y,r.size.width,r.size.height); //printf("%f,%f,%f,%f\n",NSMinX(r),NSMinY(r),NSWidth(r),NSHeight(r));// same as above if(NSPointInRect(p,r) == NO) return; //if(!messageTextField) NSRunAlertPanel(@"Warning", @"messageTextField nil!", NULL, NULL, NULL); [messageTextField setStringValue:s]; } // awakeFromNib is called when this object is done being unpacked from the nib file; // at this point, we can do any needed initialization before turning app control over to the user - (void)awakeFromNib { // We don't actually need to do anything here, so it's empty } @end
マウスイベントの座標は
NSPoint p = [event locationInWindow];
であるが、イベントはウインドウのパネルのどの場所をクリックしても発生し、mouseDown
に届くので、ボックス(box)以外から来るイベントを捨てる必要がある。
r = [box frame];// frame is a generic method for NSView class.
if(NSPointInRect(p,r) == NO)
return;
はそのためのコードである。
デバッグに使ったコードがコメントアウトして残されている。
ソースコードに現れる messageTextField
、box
の実体を Interface Builder で指定し、mouseDown
をウィンドウと結びつける必要がある。
ウィンドウの属性を表示する*。
Tools
→ Instector
を選択する>ウインドウのクラスを XMouse
に変更する。すると Class Outlets に box
と messageTextField
が表示されるはずである。
インスペクタパネルのトップバーは Mouse Identity
となっている。この Mouse
はオブジェクトのクラス名 XMouse
から自動的に(適当に)決定される。
このままでは、box
や messageTextField
の値は NULL
である。これらに Interface Builder で表示されるオブジェクトの実体を結びつける必要がある。
ウインドウを controll-click すると connections panel が表示される*。この中の box
をウインドウのボックスに messageTextField
をウインドウのテキストフィールドに結びつける。(下図)
box
をウインドウのボックスに結びつけているところ。
messageTextField
は既に結びつけ終わっている。
マウスイベントで最初に戸惑うのは、イベントの発生源が Interface Builder の中で(目に見える姿で)表示されない事である。
しかし mouseDown
は組み込みのメソッドなので、XMouse.m
の中で上書きするだけでマウスイベントはここに来る。従って以上でプログラムは動くはずである。
ソースコードの中の mouseDown
を mouseUp
や mouseDragged
に置き換えるだけで、これらのマウスイベントに反応するプログラムになる。
printf()
を使ったデバッグに関しては XSlider に解説されている。
マウスドラッグに反応するソースコード: XMouse.zip
2009/08/04
方法 1 は無駄が含まれていたと思う。XMouse.h
で定義される新しいクラスを NSBox
の派生クラスとして定義し、これを Box と結びつければ幾分簡単になる。
ここではマウスドラッグに反応する Box を扱う。
XMouse.h
XMouse.h
を次のようにする。
#import <Cocoa/Cocoa.h> @interface XMouse : NSBox { IBOutlet NSTextField *messageTextField; } - (void)mouseDragged:(NSEvent *)event; //Kenar @end
XMouse.h
今度は
IBOutlet NSBox *box;
がこの中に含まれていない事に注意しよう。
XMouse.m
XMouse.m
は
#import "XMouse.h" @implementation XMouse - (void)mouseDragged:(NSEvent *)event //Kenar { // mouse-dragged event comes here. OK NSString *s; NSPoint p = [event locationInWindow];//OK NSRect r; s = [NSString stringWithFormat:@"(%f,%f)", p.x,p.y]; r = [self frame];// frame is a generic method for NSView class. if(NSPointInRect(p,r) == NO) return; if(!messageTextField) NSRunAlertPanel(@"Warning", @"messageTextField nil!", NULL, NULL, NULL);//OK [messageTextField setStringValue:s];//NG } // awakeFromNib is called when this object is done being unpacked from the nib file; // at this point, we can do any needed initialization before turning app control over to the user - (void)awakeFromNib { // We don't actually need to do anything here, so it's empty } @end
XMouse.m
方法 1 では
r = [box frame];// frame is a generic method for NSView class.
であったが、今度は
r = [self frame];// frame is a generic method for NSView class.
となる。また今回は余分なコメントは削除されている。
ソースコードをコンパイルし、Box のインスペクタの identity で Class を XMouse にする。
Box の identity
さらに Connections で messageTextField をウインドウの中のテキストフィールドと結びつける。
Box の Connections
コンパイルして実行する。
この第二の方法が推奨される方法であるか否かは不明である。
XMouse.m
の中の
if(NSPointInRect(p,r) == NO)
return;
を削除した場合にはマウスドラッグは幾分異なった振る舞いをする。この場合にはドラッグの開始点は Box の中に制限されるが、終了点には制限が付かない。この方が使いやすい事があるかも知れない。もしも mouseDown イベントだけを扱う問題であれば、このコードは不要であろう。
マウスドラッグに反応するソースコード: XMouse1.zip
以下は参考にした URL の一覧です。