Пользовательский NSButtonCell, drawBezelWithFrame не вызывается

Я пытаюсь понять, как настраивать кнопки рисования в Cocoa/OSX. Поскольку мой вид нарисован на заказ, я не буду использовать IB и хочу сделать все это в коде. Я создал подкласс NSButtonCell и подкласс NSButton. В подклассе NSButtonCell я переопределяю метод drawBezelWithFrame:inView: и в методе initWithFrame моего подкласса NSButton я использую 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:)];
}

person Community    schedule 30.05.2013    source источник


Ответы (2)


Ниже приведены вещи, которые, кажется, отсутствуют в вашем коде.

  1. Вы не вызываете [super drawRect:dirtyRect]
  2. Вы не переопределяете + (Class)cellClass в классе (TWIButton), производном от NSButton.

Ниже приведен код после изменений:

@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 и убедитесь, что она будет вызвана.

person Abdul Naveed    schedule 31.05.2013
comment
Спасибо, работает как шарм. Метод drawRect был создан шаблоном XCode, интересно, почему они не включили супервызов. - person ; 31.05.2013
comment
CellClass устарел в OS X 10.11. Любая идея, как решить эту проблему сейчас, избегая устаревших методов? - person Thomas Tempelmann; 23.05.2016

Можно отказаться от подкласса NSButton, поскольку похоже, что вы используете его ТОЛЬКО для создания экземпляра типа Cell в инициализаторе. Просто

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

Кстати. у вас, вероятно, будет утечка в предыдущих примерах, поскольку вы инициализируете, а затем вызываете setCell, который, вероятно, имеет свой собственный метод сохранения.

person Gabe Rainbow    schedule 15.06.2013