Cocoa прокрутки кнопок с mouseEntered: и mouseExited:?

В надежде создать эффект опрокидывания кнопки, я создал подкласс NSButton под названием Button.

button.h:

#import <AppKit/AppKit.h>

@interface Button : NSButton {
}

- (void)mouseEntered:(NSEvent *)theEvent;
- (void)mouseExited:(NSEvent *)theEvent;
- (void)mouseDown:(NSEvent *)ev;
- (void)mouseUp:(NSEvent *)theEvent;

@end

Button.m:   #import "Button.h"

@implementation Button

- (id)initWithFrame:(NSRect)frameRect  {
    self = [super initWithFrame:frameRect];
    if(self != nil) {
    NSLog(@"btn init");
}
    return self;
}


- (void)mouseEntered:(NSEvent *)theEvent{
    NSLog(@"mouseEntered");
    [self setImage:[NSImage imageNamed:@"lockIcon_2.png"]];
    [self setNeedsDisplay];
}
- (void)mouseExited:(NSEvent *)theEvent{
    [self setImage:[NSImage imageNamed:@"lockIcon_1.png"]];
    NSLog(@"mouseExited");  
    [self setNeedsDisplay];
}

- (void)mouseDown:(NSEvent *)ev {
    NSLog(@"mouseDown!");
}

- (void)mouseUp:(NSEvent *)ev {
    NSLog(@"mouseUp!");
}

@end

С помощью кода выше, каждый раз, когда я нажимаю на кнопку, я вижу "mouseDown" в журналах, но я не вижу "mouseEntered" или "mouseExited" (и, конечно, не вижу изменения изображения)?? К сожалению, я знаю, что мне не хватает чего-то очевидного, но я просто не вижу его...???

Ответ 1

Проблема заключается в том, что NSButton может обрабатывать некоторые события мыши только в том случае, если вы добавляете свою настраиваемую кнопку NSTrackingArea к кнопке.

Попробуйте добавить этот код в свой класс кнопок. Это помогло мне. Также вы можете играть с вариантами, если они вас не удовлетворили.

- (void)createTrackingArea
{
    NSTrackingAreaOptions focusTrackingAreaOptions = NSTrackingActiveInActiveApp;
    focusTrackingAreaOptions |= NSTrackingMouseEnteredAndExited;
    focusTrackingAreaOptions |= NSTrackingAssumeInside;
    focusTrackingAreaOptions |= NSTrackingInVisibleRect;

    NSTrackingArea *focusTrackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect
            options:focusTrackingAreaOptions owner:self userInfo:nil];
    [self addTrackingArea:focusTrackingArea];
}


- (void)awakeFromNib
{
    [self createTrackingArea];
}

Надеюсь, что это поможет.

Ответ 2

Хотя настройка области отслеживания, безусловно, является способом сделать это, NSButton/NSButtonCell уже имеют эту встроенную функциональность.

Извлечение NSButton showsBorderOnlyWhileMouseInside, и соответствующие NSButtonCell mouseEntered и mouseExited. Это задокументировано здесь:

https://developer.apple.com/documentation/appkit/nsbuttoncell/1527903-showsborderonlywhilemouseinside

В зависимости от вашего варианта использования, это может или не может работать. Для меня я все равно подклассифицировал NSButtonCell, так что это было прекрасно. Следует помнить, что это также влияет на вызовы drawBezel.