自定义NSButtonCell,不调用drawBezelWithFrame

时间:2013-05-30 14:12:29

标签: macos cocoa subclass nsbutton nsbuttoncell

我正在试图弄清楚如何在Cocoa / OSX中自定义绘制按钮。由于我的视图是自定义绘制的,因此我不会使用IB并希望在代码中完成所有操作。我创建了NSButtonCell的子类和NSButton的子类。在NSButtonCell的子类中,我重写了方法drawBezelWithFrame:inView:并且在我的子类NSButton的initWithFrame方法中,我使用setCell在Button中设置我的CustomCell。但是,drawBezelWithFrame没有被调用,我不明白为什么。有人可以指出我做错了什么或我错过了什么?

NSButtonCell的子类:

#import "TWIButtonCell.h"

@implementation TWIButtonCell

-(void)drawBezelWithFrame:(NSRect)frame inView:(NSView *)controlView
{
    //// General Declarations
[[NSGraphicsContext currentContext] saveGraphicsState];

    //// Color Declarations
    NSColor* fillColor = [NSColor colorWithCalibratedRed: 0 green: 0.59 blue: 0.886 alpha: 1];

    //// Rectangle Drawing
    NSBezierPath* rectanglePath = [NSBezierPath bezierPathWithRect: NSMakeRect(8.5, 7.5, 85, 25)];
    [fillColor setFill];
    [rectanglePath fill];
    [NSGraphicsContext restoreGraphicsState];
}

@end

NSButton的子类:

#import "TWIButton.h"
#import "TWIButtonCell.h"

@implementation TWIButton

- (id)initWithFrame:(NSRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        TWIButtonCell *cell = [[TWIButtonCell alloc]init];
        [self setCell:cell];
    }

    return self;
}

- (void)drawRect:(NSRect)dirtyRect
{
    // Drawing code here.
}

@end

用法:

- (void)addSendButton:(NSRect)btnSendRectRect 
{
    TWIButton *sendButton = [[TWIButton alloc] initWithFrame:btnSendRectRect];
    [self addSubview:sendButton];
    [sendButton setTitle:@"Send"];
    [sendButton setTarget:self];
    [sendButton setAction:@selector(send:)];
}

2 个答案:

答案 0 :(得分:4)

以下内容似乎从您的代码中遗漏了。

  1. 您没有调用[super drawRect:dirtyRect]
  2. 您没有覆盖从NSButton派生的类(TWIButton)中的 +(Class)cellClass
  3. 以下是更改后的代码:

    @implementation TWIButton
    
        - (id)initWithFrame:(NSRect)frame
        {
            self = [super initWithFrame:frame];
            if (self)
            {
                TWIButtonCell *cell = [[TWIButtonCell alloc]init];
                [self setCell:cell];
            }
    
            return self;
        }
    
        - (void)drawRect:(NSRect)dirtyRect
        {
            // Drawing code here.
           //Changes Added!!!
        [super drawRect:dirtyRect];
    
        }
    
        //Changes Added!!!!
        + (Class)cellClass
        {
           return [TWIButtonCell class];
        }
    
        @end
    

    现在将断点保持在drawBezelWithFrame并检查它是否会被调用。

答案 1 :(得分:2)

有人可能放弃NSButton子类,因为看起来你只是用它来实例化初始化器中的Cell类型。 简单地

NSButton *button ...
[button setCell: [[TWIButtonCell alloc] init] autorelease]];

顺便说一句。你可能在前面的例子中有一个泄漏,因为你初始化然后调用可能有自己的保留的setCell。