NSButton: show alternate image on hover

纵然是瞬间 提交于 2019-12-10 19:49:10

问题


I've a NSButton with both an Image and Alternate Image. I would like the alternate image to be shown on hover. To solve this, I've extended the NSButton to show the alternate image when hovering the view. Is there a better solution to this?

My solution:

@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

回答1:


I would say this is better suited to an NSButtonCell subclass. you can do it in one method and it won't apply to all NSButtons (I doubt thats what you actually want). Just set your button cell type in IB to your custom subclass.

here is some code I just wrote and tested that works:

- (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];
    }
}

you will need to set the showsBorderOnlyWhileMouseInside to YES probably in an init method for the cell.




回答2:


CustomButton.h

@interface CustomButton : NSButton
@property (getter=isMouseInside) BOOL mouseInside;
@end

CustomButton.m

@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

CustomButtonCell.h

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

CustomButtonCell.m

@implementation CustomButtonCell
@end

Also see this answer.



来源:https://stackoverflow.com/questions/19859782/nsbutton-show-alternate-image-on-hover

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!