NSButton/NSButtonCellのサブクラス作成中
NSButtonの描画周りを弄りたいので,NSButtonCellのサブクラスを作ったりしている.
しかしこれが思った通りに行かないので,次のようなMyButtonなるサブクラスを作って,Interface Builderで配置したNSButtonのカスタムクラスに設定してみた.
@interface MyButton : NSButton {} @end
@interface MyButtonCell : NSButtonCell {} @end
@implementation MyButton
+ (Class)cellClass {
return [MyButtonCell class];
}
@end
@implementation MyButtonCell
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
NSLog(@"drawWithFrame:inView:");
[super drawWithFrame:cellFrame inView:controlView];
}
@end
期待される挙動は単純で,NSButtonが描画される際にコンソールに"drawWithFrame:inView:"と表示されるというもの.だが実際にはその通りに動作せず,コンソールに"drawWithFrame:inView:"が吐き出されない.
そこで少し手法を変えて,ためしに適当なNSApplicationのデリゲートを作って次のようにしてみた. ただしmyButtonはMyButtonのインスタンス(アウトレット).
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
MyButtonCell *myButtonCell = [[[MyButtonCell alloc] init] autorelease];
[myButton setCell:myButtonCell];
}
これなら一応うまく行く.ただボタンの種類をNSDisclosureBezelStyleに設定すると,三角形の挙動が明らかにおかしい.開くときに三角形が斜めに向いてまたすぐ閉じた状態に戻る.引き続き弄ってみるつもり.
追記@07/14 18:00
上の例でNSApplicationのデリゲートを利用する必要があった理由として,Knowledge Baseによると,「Interface BuilderのパレットからNSButtonを配置した時点でデフォルトとしてNSButtonCellが設定されているのだから,専用のパレットを作製するか,もしくはinitWithCoder:を上書きする必要がある」ことが考えられる.
あとNSDisclosureBezelStyleなボタンのサブクラス作製だけれども,なんかmouseUp:が呼ばれていないっぽい.これが変な理由?
追記@07/14 19:00
NSDisclosureBezelStyleなボタンの挙動がおかしいのは,NSButtonCellのinit内で[self setButtonType:NSOnOffButtonType];をしたら期待通りの挙動になった.というわけで,NSDisclosureBezelStyleなボタンのサブクラスを作るために必要な@implementationをまとめてみる.@interfaceは上のままで,特に追加するものはない.
@implementation MyButton
+ (Class)cellClass {
return [MyButtonCell class];
}
/*
initWithCoder:のオーバーライドはInterFace BuilderからNSButtonを配置してカスタムクラスを設定した場合に必要だけど,
IBからCustom Viewを配置してCustom ClassにMyButtonを設定した場合には不要っぽい.
*/
- (id)initWithCoder:(NSCoder *)coder
{
if (self = [super initWithCoder:coder]) {
[self setCell:[[[MyButtonCell alloc] init] autorelease];
}
return self;
}
@end
@implementation MyButtonCell
- (id)init
{
if (self = [super init]) {
[self setBezelStyle:NSDisclosureBezelStyle]; //NSDisclosureBezelStyleなボタンを作ります.
[self setButtonType:NSOnOffButton]; // NSDisclosureBezelStyleには必須
[self setTitle:nil]; // タイトルは邪魔
}
return self;
}
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
NSLog(@"drawWithFrame:inView:"); // これがコンソールに表示されればOK
[super drawWithFrame:cellFrame inView:controlView];
}
@end