【问题标题】:Custom NSButtonCell, drawBezelWithFrame not called自定义 NSButtonCell,drawBezelWithFrame 未调用
【发布时间】:2013-05-26 04:01:25
【问题描述】:

我试图弄清楚如何在 Cocoa/OSX 中自定义绘制按钮。由于我的视图是自定义绘制的,因此我不会使用 IB,而是希望在代码中完成所有操作。我创建了 NSButtonCell 的子类和 NSButton 的子类。在 NSButtonCell 的子类中,我覆盖了方法 drawBezelWithFrame:inView: 并在我的子类 NSButton 的 initWithFrame 方法中,我使用 setCell 在按钮中设置了我的 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:)];
}

【问题讨论】:

    标签: macos cocoa subclass nsbutton nsbuttoncell


    【解决方案1】:

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

    1. 你没有调用 [super drawRect:dirtyRect]
    2. 您没有在派生自 NSButton 的 Class(TWIButton) 中覆盖 + (Class)cellClass

    修改后的代码如下:

    @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 并检查它是否会被调用。

    【讨论】:

    • 谢谢你,就像一个魅力。 drawRect 方法是由 XCode 模板创建的,想知道为什么它们没有包含 super 调用。
    • cellClass 在 OS X 10.11 中已被弃用。知道如何通过避免弃用的方法来解决它吗?
    【解决方案2】:

    人们可能会放弃 NSButton 子类,因为看起来您只是在使用它来实例化初始化程序中的 Cell 类型。 简单的

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

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

    【讨论】:

      猜你喜欢
      • 2012-11-03
      • 1970-01-01
      • 2021-03-10
      • 1970-01-01
      • 2015-09-13
      • 2013-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多