[Cocoa] Target & Action, 另外一种响应事件的方法
2008-04-25 18:10
399 查看
[Cocoa] Target & Action, 另外一种响应事件的方法
我们知道在Cocoa程序中, 如果你想处理一个窗口的事件或者应用程序的事件, 你可以使用Delegate的方法来实现响应的事件处理函数,但是如果你要处理一个button控件或者一个窗口里面很多的类似Button的这种有一种 缺省行为的控件的时候, 是不是要为他们每个控件都来实现这个Delegate呢?答案是否定的,因为针对这些具有指定的缺省行为的控件,NSControl已经帮我们进行了一部 分的处理(这个control要求继承自NSActionCell, 比如你添加一个Button到窗口中,那么对Button的Click事件,NSControl是有自己的处理的,这就是Target-Action模 式,当Button的click事件被触发是,NSControl就会去检查这个Control中是否有对应的Target,这个Target针对这个事 件处理的Action是什么,如果Target和Action都存在,那么这个Click事件就会被NSControl直接处理,类似的处理代码如下(假 设的实现)
-(void) mouseClicked()
{
if (target != nil && action != nil && [target respondsToSelector:action])
{
[target performSelector:action withObject:self];
}
}
下面我们通过具体的代码来展示一下这个技术。
#import <Cocoa/Cocoa.h>
@interface MyController : NSObject
{
}
- (void) onButtonClicked:(id)sender;
@end
@implementation MyController
- (void) onButtonClicked:(id)sender
{
[NSApp terminate:NSApp];
}
@end
int main(int argc, char *argv[])
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
[NSApplication sharedApplication];
//Create main window
NSRect rc = NSMakeRect(0, 0, 800, 600);
NSUInteger uiStyle = NSTitledWindowMask | NSResizableWindowMask | NSClosableWindowMask;
NSBackingStoreType backingStoreStyle = NSBackingStoreBuffered;
NSWindow* win = [[NSWindow alloc] initWithContentRect:rc styleMask:uiStyle backing:backingStoreStyle defer:NO];
[win setTitle:@"HelloWin Test"];
//Create a button and set it as content view
NSButton* button = [[NSButton alloc] initWithFrame:NSMakeRect(200, 200, 60, 40)];
[button setTitle:@"Quit Application"];
[win setContentView:button];
//Set target and action
MyController* controller = [[MyController alloc] init];
[button setTarget:controller];
[button setAction:@selector(onButtonClicked:)];
[win center]; //Center main Window
[win makeKeyAndOrderFront:win];
[win makeMainWindow];
[NSApp run];
[button release];
[win release];
[pool drain];
return 0;
}
上 面这段代码首先创建了一个窗口,然后在窗口内创建了一个Button,这个Button作为窗口的ContentView呈现,因为NSButton是从 NSView继承来的,所以也是NSView的一个实例。在创建了Button对象之后,我们就为这个Button对象设置了用来处理缺省事件的 Target对象,然后又通过setAction来设置处理这个事件的方法, 这里要注意的是这个Action方法一定是可以被Target响应的,也就是说符合respondsToSelector:的调用。
这个 Target对象的实现被放在一个叫做MyController的类里面,它实现了一个方法叫做onButtonClicked:,这个方法被作为一个 Action方法,所以它有一个参数(id)sender,这是因为Action方法被调用的时候,调用者会将触发这个Action的对象通过这个参数传 递给Action方法。这个例子的实现很简单,直接调用NSApp对象的Terminate:方法来退出应用程序。
这个例子结束的地方和 以前有所不同, 我分别调用了Button和Window的release方法,这是因为Window和Button对象都是通过引用形式分配的,所以当不再需要使用的时 候需要将他们所占用的资源释放掉。Obj-C 2.0中提供了Garbage Colletion的功能,你分配的对象会在不被使用的时候自动释放,不过如果能了解Cocoa对象的分配和释放模式,对我们理解整个Cocoa框架的实 现还是大有益处的。
上面这个例子还有一个地方需要注意的是Button的大小,你可以看到在代码中我为button分配的Rect的大小 是60x40,但是运行的时候你会发现这个Button充满了整个Windows的Content区域,这是因为这个Button作为Window的ContentView,而Window的ContentView的Size Policy是随父窗口改变高度和宽度的。如果我们将
[win setContentView:button];
这句代码注释掉,换成下面的这句
[[win contentView] addSubview:button];
那么这个Button就在窗口中被正确定位了, 但是当你改变窗口大小的时候,这个Button的位置和大小都没有改变,这个是由它的Sizing Policy决定的。
我们知道在Cocoa程序中, 如果你想处理一个窗口的事件或者应用程序的事件, 你可以使用Delegate的方法来实现响应的事件处理函数,但是如果你要处理一个button控件或者一个窗口里面很多的类似Button的这种有一种 缺省行为的控件的时候, 是不是要为他们每个控件都来实现这个Delegate呢?答案是否定的,因为针对这些具有指定的缺省行为的控件,NSControl已经帮我们进行了一部 分的处理(这个control要求继承自NSActionCell, 比如你添加一个Button到窗口中,那么对Button的Click事件,NSControl是有自己的处理的,这就是Target-Action模 式,当Button的click事件被触发是,NSControl就会去检查这个Control中是否有对应的Target,这个Target针对这个事 件处理的Action是什么,如果Target和Action都存在,那么这个Click事件就会被NSControl直接处理,类似的处理代码如下(假 设的实现)
-(void) mouseClicked()
{
if (target != nil && action != nil && [target respondsToSelector:action])
{
[target performSelector:action withObject:self];
}
}
下面我们通过具体的代码来展示一下这个技术。
#import <Cocoa/Cocoa.h>
@interface MyController : NSObject
{
}
- (void) onButtonClicked:(id)sender;
@end
@implementation MyController
- (void) onButtonClicked:(id)sender
{
[NSApp terminate:NSApp];
}
@end
int main(int argc, char *argv[])
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
[NSApplication sharedApplication];
//Create main window
NSRect rc = NSMakeRect(0, 0, 800, 600);
NSUInteger uiStyle = NSTitledWindowMask | NSResizableWindowMask | NSClosableWindowMask;
NSBackingStoreType backingStoreStyle = NSBackingStoreBuffered;
NSWindow* win = [[NSWindow alloc] initWithContentRect:rc styleMask:uiStyle backing:backingStoreStyle defer:NO];
[win setTitle:@"HelloWin Test"];
//Create a button and set it as content view
NSButton* button = [[NSButton alloc] initWithFrame:NSMakeRect(200, 200, 60, 40)];
[button setTitle:@"Quit Application"];
[win setContentView:button];
//Set target and action
MyController* controller = [[MyController alloc] init];
[button setTarget:controller];
[button setAction:@selector(onButtonClicked:)];
[win center]; //Center main Window
[win makeKeyAndOrderFront:win];
[win makeMainWindow];
[NSApp run];
[button release];
[win release];
[pool drain];
return 0;
}
上 面这段代码首先创建了一个窗口,然后在窗口内创建了一个Button,这个Button作为窗口的ContentView呈现,因为NSButton是从 NSView继承来的,所以也是NSView的一个实例。在创建了Button对象之后,我们就为这个Button对象设置了用来处理缺省事件的 Target对象,然后又通过setAction来设置处理这个事件的方法, 这里要注意的是这个Action方法一定是可以被Target响应的,也就是说符合respondsToSelector:的调用。
这个 Target对象的实现被放在一个叫做MyController的类里面,它实现了一个方法叫做onButtonClicked:,这个方法被作为一个 Action方法,所以它有一个参数(id)sender,这是因为Action方法被调用的时候,调用者会将触发这个Action的对象通过这个参数传 递给Action方法。这个例子的实现很简单,直接调用NSApp对象的Terminate:方法来退出应用程序。
这个例子结束的地方和 以前有所不同, 我分别调用了Button和Window的release方法,这是因为Window和Button对象都是通过引用形式分配的,所以当不再需要使用的时 候需要将他们所占用的资源释放掉。Obj-C 2.0中提供了Garbage Colletion的功能,你分配的对象会在不被使用的时候自动释放,不过如果能了解Cocoa对象的分配和释放模式,对我们理解整个Cocoa框架的实 现还是大有益处的。
上面这个例子还有一个地方需要注意的是Button的大小,你可以看到在代码中我为button分配的Rect的大小 是60x40,但是运行的时候你会发现这个Button充满了整个Windows的Content区域,这是因为这个Button作为Window的ContentView,而Window的ContentView的Size Policy是随父窗口改变高度和宽度的。如果我们将
[win setContentView:button];
这句代码注释掉,换成下面的这句
[[win contentView] addSubview:button];
那么这个Button就在窗口中被正确定位了, 但是当你改变窗口大小的时候,这个Button的位置和大小都没有改变,这个是由它的Sizing Policy决定的。
相关文章推荐
- Target & Action, 另外一种响应事件的方法
- 【Tutorial】Target & Action, 另外一种响应事件的方法
- Cocoa系列教学三:Target & Action, 另外一种响应事件
- ios target-action响应方法的不同形式
- 【DM642学习笔记一】关于Can't Initialize Target CPU的一种解决方法(Error 0x80000240/-10
- 判断TCP通信结束的方法&&相对于trace有另外一种监测方法:monitor
- 【Unity&事件】事件监听响应的几种方法分析研究
- 一种C#读写二进制文件的通用方法<转>
- Trafodion Rename Table不成功的另外一种解决方法
- C#WinForm中按钮响应回车事件的简单方法
- ios iphone旋转响应的方法
- andorid布局layout监听点击事件,布局内的imageButton无法响应解决方法
- VC中使用CRichEdit不能响应鼠标事件解决方法
- 极速响应Excel数据报表请求的一种方法
- 在Activity中响应ListView内部按钮的点击事件的两种方法!!!
- E语言一种特殊的找按钮事件方法
- java常见事件响应方法实例汇总
- OpenCV响应鼠标事件&改变像素颜色
- 解决android ListView item中事件处理无法响应方法