Objective c NSButton:悬停时显示备用图像

Objective c NSButton:悬停时显示备用图像,objective-c,nsbutton,Objective C,Nsbutton,我有一个带有图像和备用图像的NSButton。我想在悬停时显示备用图像。为了解决这一问题,我扩展了NSB按钮,以便在悬停视图时显示备用图像。有更好的解决办法吗 我的解决方案: @interface HoverButton() @property (nonatomic, strong) NSTrackingArea *trackingArea; @property (nonatomic, strong) NSImage *imageTmp; @end @implementation HoverB

我有一个带有图像和备用图像的
NSButton
。我想在悬停时显示备用图像。为了解决这一问题,我扩展了NSB按钮,以便在悬停视图时显示备用图像。有更好的解决办法吗

我的解决方案:

@interface HoverButton()
@property (nonatomic, strong) NSTrackingArea *trackingArea;
@property (nonatomic, strong) NSImage *imageTmp;
@end

@implementation HoverButton

-(void)mouseEntered:(NSEvent *)theEvent {
    [super mouseEntered:theEvent];

    [self updateImages];
    self.image = self.alternateImage;
}

-(void)mouseExited:(NSEvent *)theEvent {
    [super mouseExited:theEvent];

    self.image = self.imageTmp;
}

- (void)updateImages {
    self.imageTmp = self.image;
}

-(void)updateTrackingAreas
{
    if(self.trackingArea != nil) {
        [self removeTrackingArea:self.trackingArea];
    }

    int opts = (NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways);
    self.trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
                                                     options:opts
                                                       owner:self
                                                    userInfo:nil];

    [self addTrackingArea:self.trackingArea];
}


@end

我认为这更适合
NSButtonCell
子类。你可以用一种方法来做,但它不会适用于所有的按钮(我怀疑这是你真正想要的)。只需将IB中的按钮单元类型设置为自定义子类

以下是我刚刚编写并测试的一些代码:

- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
    if (_alternateImageOrKeyEquivalentFont && _bcFlags2.mouseInside) {
        // the draw bezel call is optional. maybe you don't want it
        [self drawBezelWithFrame:cellFrame inView:controlView];
        [self drawImage:_alternateImageOrKeyEquivalentFont
              withFrame:cellFrame
                 inView:controlView];
    } else {
        [super drawInteriorWithFrame:cellFrame
                              inView:controlView];
    }
}
您可能需要在单元格的
init
方法中将
showsborderonlywhilemouseind
设置为
YES

CustomButton.h

自定义按钮

CustomButtonCell.h

CustomButtonCell.m


也可以看到这一点。

当这起作用时,它将通过应用商店被拒绝,因为
\u alternativeImageWorkeyeEquivalentFont
\u bcFlags2
是私有api。@Zenox是什么让它们成为私有的?它们在头文件中声明为正确的,以供世界查看。我不知道确切的规则是什么,因为我不在应用商店上发布;请开导我。这对什么是私密有一个很好的答案:。对于这个具体的例子:。@Zenox谢谢,这当然可以回答:)我会尽量记得在有时间的时候用合适的非私有解决方案更新这个答案。对于mouseInside,您只需在
NSButtonCell
子类中实现
-mouseenterned:
-mouseExited:
,并设置本地
mouseInside
属性。
@interface CustomButton : NSButton
@property (getter=isMouseInside) BOOL mouseInside;
@end
@implementation CustomButton

+ (Class)cellClass
{
    return [CustomButtonCell class];
}

- (instancetype)initWithFrame:(NSRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        [self commonCustomButtonInit];
    }
    return self;
}

- (void)commonCustomButtonInit
{
    NSTrackingArea *trackingArea = nil;
    trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
                                                options:NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways | NSTrackingInVisibleRect
                                                  owner:self
                                               userInfo:nil];

    [self addTrackingArea:trackingArea];
}


- (void)mouseEntered:(NSEvent *)event
{
    self.mouseInside = YES;
    if ([self.cell isKindOfClass:[CustomButtonCell class]])
    {
        CustomButtonCell *cell = self.cell;
        cell.mouseInside = YES;
    }
}

-(void)mouseExited:(NSEvent *)event
{
    self.mouseInside = NO;
    if ([self.cell isKindOfClass:[CustomButtonCell class]])
    {
        CustomButtonCell *cell = self.cell;
        cell.mouseInside = NO;
    }
}

@end
@interface CustomButtonCell : NSButtonCell
@property (getter=isMouseInside) BOOL mouseInside;
@end
@implementation CustomButtonCell
@end