Objective c 如何用自定义NSButtonCell以编程方式分配NSButton的子类?

Objective c 如何用自定义NSButtonCell以编程方式分配NSButton的子类?,objective-c,nsbutton,nsbuttoncell,Objective C,Nsbutton,Nsbuttoncell,我正在尝试创建一个NSButton的子类,它也使用NSButtonCell的子类,但我不能在代码中这样做 这是我的NSButonCell子类,如果我在IB中创建按钮并直接在IB中设置他的单元格类,它会工作得很好: #import "MyCustomCell.h" @implementation MyCustomCell - (void)drawImage:(NSImage*)image withFrame:(NSRect)frame inView:(NSView*)controlView {

我正在尝试创建一个
NSButton
的子类,它也使用
NSButtonCell
的子类,但我不能在代码中这样做

这是我的NSButonCell子类,如果我在IB中创建按钮并直接在IB中设置他的单元格类,它会工作得很好:

#import "MyCustomCell.h"

@implementation MyCustomCell

- (void)drawImage:(NSImage*)image withFrame:(NSRect)frame inView:(NSView*)controlView
{
    NSGraphicsContext *ctx = [NSGraphicsContext currentContext];
    CGContextRef contextRef = [ctx graphicsPort];

    NSData *data = [image TIFFRepresentation];
    CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)data, NULL);
    if(source) {
        CGImageRef imageRef = CGImageSourceCreateImageAtIndex(source, 0, NULL);
        CFRelease(source);

        CGContextSaveGState(contextRef);
        {
            NSRect rect = NSOffsetRect(frame, 0.0f, 1.0f);
            CGFloat white = [self isHighlighted] ? 0.2f : 0.35f;
            CGContextClipToMask(contextRef, NSRectToCGRect(rect), imageRef);
            [[NSColor colorWithDeviceWhite:white alpha:1.0f] setFill];
            NSRectFill(rect);
        } 
        CGContextRestoreGState(contextRef);

        CGContextSaveGState(contextRef);
        {
            NSRect rect = frame;
            CGContextClipToMask(contextRef, NSRectToCGRect(rect), imageRef);
            [[NSColor colorWithDeviceWhite:0.1f alpha:1.0f] setFill];
            NSRectFill(rect);
        } 
        CGContextRestoreGState(contextRef);        

        CFRelease(imageRef);
    }
 }

 - (void)drawBezelWithFrame:(NSRect)frame inView:(NSView *)controlView
 {
    NSGraphicsContext *ctx = [NSGraphicsContext currentContext];

    CGFloat roundedRadius = 3.0f;

    BOOL outer = YES;
    BOOL background = YES;
    BOOL stroke = YES;
    BOOL innerStroke = YES;

    if(outer) {
        [ctx saveGraphicsState];
        NSBezierPath *outerClip = [NSBezierPath bezierPathWithRoundedRect:frame   xRadius:roundedRadius yRadius:roundedRadius];
        [outerClip setClip];

        NSGradient *outerGradient = [[NSGradient alloc] initWithColorsAndLocations:
                                 [NSColor colorWithDeviceWhite:0.20f alpha:1.0f], 0.0f, 
                                 [NSColor colorWithDeviceWhite:0.21f alpha:1.0f], 1.0f, 
                                 nil];

        [outerGradient drawInRect:[outerClip bounds] angle:90.0f];
        [outerGradient release];
        [ctx restoreGraphicsState];
    }

    if(background) {
        [ctx saveGraphicsState];
        NSBezierPath *backgroundPath = [NSBezierPath bezierPathWithRoundedRect:NSInsetRect(frame, 2.0f, 2.0f) xRadius:roundedRadius yRadius:roundedRadius];
        [backgroundPath setClip];

        NSGradient *backgroundGradient = [[NSGradient alloc] initWithColorsAndLocations:
                                      [NSColor colorWithDeviceWhite:0.17f alpha:1.0f], 0.0f, 
                                      [NSColor colorWithDeviceWhite:0.20f alpha:1.0f], 0.12f, 
                                      [NSColor colorWithDeviceWhite:0.27f alpha:1.0f], 0.5f, 
                                      [NSColor colorWithDeviceWhite:0.30f alpha:1.0f], 0.5f, 
                                      [NSColor colorWithDeviceWhite:0.42f alpha:1.0f], 0.98f, 
                                      [NSColor colorWithDeviceWhite:0.50f alpha:1.0f], 1.0f, 
                                      nil];

        [backgroundGradient drawInRect:[backgroundPath bounds] angle:270.0f];
        [backgroundGradient release];
        [ctx restoreGraphicsState];
    }

    if(stroke) {
        [ctx saveGraphicsState];
        [[NSColor colorWithDeviceWhite:0.12f alpha:1.0f] setStroke];
        [[NSBezierPath bezierPathWithRoundedRect:NSInsetRect(frame, 1.5f, 1.5f) xRadius:roundedRadius yRadius:roundedRadius] stroke];
        [ctx restoreGraphicsState];
    }

    if(innerStroke) {
        [ctx saveGraphicsState];
        [[NSColor colorWithDeviceWhite:1.0f alpha:0.05f] setStroke];
        [[NSBezierPath bezierPathWithRoundedRect:NSInsetRect(frame, 2.5f, 2.5f) xRadius:roundedRadius yRadius:roundedRadius] stroke];
        [ctx restoreGraphicsState];        
    }

    if([self isHighlighted]) {
        [ctx saveGraphicsState];
        [[NSBezierPath bezierPathWithRoundedRect:NSInsetRect(frame, 2.0f, 2.0f) xRadius:roundedRadius yRadius:roundedRadius] setClip];
        [[NSColor colorWithCalibratedWhite:0.0f alpha:0.35] setFill];
        NSRectFillUsingOperation(frame, NSCompositeSourceOver);
        [ctx restoreGraphicsState];
    }
}

@end
我还创建了一个自定义的
NSButton
子类,它使用这个
NSButtonCell

#import "myButton.h"
#import "MyCustomCell.h"

@implementation myButton

- (id)initWithFrame:(NSRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        [self setCell:[[MyCustomCell alloc] init]];
        self.image = [NSImage imageNamed:@"add"];

    }

    return self;
}

@end

但是当我在视图中创建这个按钮时,按钮的外观是默认的,而不是
NSButtonCell
子类的定制样式。如果我在IB中设置单元格,那么所有单元格都可以很好地工作,但在代码中则不行。有人有办法解决这个问题吗?谢谢

您是否尝试过使用cellClass方法

+ (Class)cellClass {
    return MyCustomCell.class;
}

我知道如何解决这个问题


需要在调用
setBezelStyle
的按钮上设置挡板样式。使用这一行代码,除了图像是颠倒的以外,所有的工作都很好。

您是否在代码中尝试过-initWithNibName:bundle:for MyCustomCell初始化,比如[self-setCell:[[MyCustomCell alloc]initWithNibName:@“nibName”bundle:nil]?我不想用nib-o-xib。我不想在myButton类中设置断点时分配所有代码,
-initWithFrame:
是否会被调用?这看起来应该可以正常工作。是的,myButton类中的
-initWithFrame:
被调用。有点不对劲,但我不明白是什么。对我来说,目前使用XIB是一个大问题。是的,我也尝试过使用
cellClass
方法,但仍然不起作用!似乎唯一的解决方案是使用XIB文件,但这是一种非常奇怪的情况:应该可以通过代码来实现。