在NSButton子类中的mouseDown之后不再调用mouseExited

时间:2018-04-24 16:29:36

标签: cocoa mouseevent nsbutton nsevent

在构建自定义NSButton时,我遇到了处理突出显示行为的问题。单击按钮,按住并将光标拖动到按钮边界之外,不会传递mouseExited:mouseEntered:个事件。我理解原因,因为mouseDown:调用[super mouseDown:event];将阻止点击发布。

在研究这个问题时,我遇到了this Stack Overflow post,它描述了同样的问题。提到的解决方案是将NSTrackingEnabledDuringMouseDrag添加到我已完成的NSTrackingArea选项中,但我仍然会看到此问题。我尝试了另一个提出的解决方案,在循环中处理下一个事件,但这导致奇怪的行为。按钮文本颜色在鼠标按下时变黑,而不是突出显示变暗的颜色,并且在释放鼠标时它不会不亮,它仍然是黑色。

我正在使用Xcode 9.3,在macOS 10.13.4上运行。

这是我的NSButton子类:

@interface BorderlessButton : NSButton {
    NSColor *_tempColor;
}

@property (strong, nonatomic) NSColor *color;

@end

@interface BorderlessButton ()

@property (nonatomic) BOOL pressed;

@end

@implementation BorderlessButton

- (id)init {
    if (self = [super init]) {
        [self setUp];
    }
    return self;
}

- (id)initWithFrame:(NSRect)frameRect {
    if (self = [super initWithFrame:frameRect]) {
        [self setUp];
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        [self setUp];
    }
    return self;
}

- (void)setUp {
    _color = [NSColor redColor];

    [self setTitle:self.title];
    [self setButtonType:NSButtonTypeMomentaryChange];
    [self setBordered:NO];

    NSTrackingArea *area = [[NSTrackingArea alloc] initWithRect:self.bounds
                                                        options:NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways | NSTrackingEnabledDuringMouseDrag
                                                          owner:self
                                                       userInfo:nil];
    [self addTrackingArea:area];
}

- (void)setTitle:(NSString *)title {
    [super setTitle:title];

    NSMutableAttributedString *colorTitle = [[NSMutableAttributedString alloc] initWithAttributedString:[self attributedTitle]];
    [colorTitle addAttributes:@{NSFontAttributeName: self.font, NSForegroundColorAttributeName: self.color} range:NSMakeRange(0, [colorTitle length])];
    [self setAttributedTitle:colorTitle];
}

- (void)setColor:(NSColor *)color {
    _color = color;

    [self setTitle:self.title];
}

- (void)mouseDown:(NSEvent *)event {
    self.pressed = YES;
    [self highlight:YES];
    [super mouseDown:event]; // this blocks until released
    [self mouseUp:event];
}

- (void)mouseUp:(NSEvent *)event {
    self.pressed = NO;
    [self highlight:NO];
    [super mouseUp:event];
}

//FIXME: Not called after mouse press down and hold then exit
- (void)mouseExited:(NSEvent *)event {
    if (self.pressed) {
        [self highlight:NO];
    }
    [super mouseExited:event];
}

- (void)mouseEntered:(NSEvent *)event {
    if (self.pressed) {
        [self highlight:YES];
    }
    [super mouseEntered:event];
}

- (void)highlight:(BOOL)flag {
    if (flag) {
        if (self.isEnabled) {
            NSColor *dimmedColor = [self dimmedColor];
            _tempColor = _color;
            self.color = dimmedColor;
            [self setTitle:self.title];
        }
    } else {
        if (self.isEnabled) {
            self.color = _tempColor;
            [self setTitle:self.title];
        }
    }
}

- (NSColor *)dimmedColor {
    return [self.color colorWithAlphaComponent:0.5];
}

@end

0 个答案:

没有答案