문제

I've implemented an NSButton with an image in it.

When the user hovers it, the image changes to something else, and then back on.


Normal Status :

enter image description here

On Hover :

enter image description here


The code I'm using for the NSButtonCell is :

Interface :

#import <Foundation/Foundation.h>

@interface DKHoverButtonCell : NSButtonCell 
{
    NSImage *_oldImage;
    NSImage *hoverImage;
}

@property (retain) NSImage *hoverImage;

@end

Implementation :

#import "DKHoverButtonCell.h"

@interface NSButtonCell()
- (void)_updateMouseTracking;
@end

@implementation DKHoverButtonCell

@synthesize hoverImage;

- (void)mouseEntered:(NSEvent *)event {
    if (hoverImage != nil && [hoverImage isValid]) {
        _oldImage = [[(NSButton *)[self controlView] image] retain];
        [(NSButton *)[self controlView] setImage:hoverImage];
    }
}

- (void)mouseExited:(NSEvent *)event {
    if (_oldImage != nil && [_oldImage isValid]) {
        [(NSButton *)[self controlView] setImage:_oldImage];
        [_oldImage release];
        _oldImage = nil;
    }
}

- (void)_updateMouseTracking {
    [super _updateMouseTracking];
    if ([self controlView] != nil && [[self controlView] respondsToSelector:@selector(_setMouseTrackingForCell:)]) {
        [[self controlView] performSelector:@selector(_setMouseTrackingForCell:) withObject:self];
    }
}

- (void)setHoverImage:(NSImage *)newImage {
    [newImage retain];
    [hoverImage release];
    hoverImage = newImage;
    [[self controlView] setNeedsDisplay:YES];
}

- (void)dealloc {
    [_oldImage release];
    [hoverImage release];
    [super dealloc];
}

@end

Now, here is the issue :

  • although the above controls works 100% (with a "X" rounded image, and transparent background"), when the user clicks on it, it displays a "white"-ish background, and not retain my old "transparent" background
  • How should I go about resolving this?
도움이 되었습니까?

해결책

You need to change button's type to Momentary Change. You can change it in Attributes inspector:

how to do it

Or change programatically:

[button setButtonType:NSMomentaryChangeButton];

다른 팁

But for your case it should be sufficient to use showsBorderOnlyWhileMouseInside property of NSButtonCell which has been around since the beginning (OS X 10.0). This would show the button's border only when the mouse is hovering inside the button. Combine that with a border style that is filled and light gray, it would be pretty close to the result you've achieved.

There's no subclassing required nor using undocumented API functions (in your case, _updateMouseTracking).

closeButton.bezelStyle = .inline
closeButton.setButtonType(.momentaryPushIn)

if let buttonCell = closeButton.cell as? NSButtonCell {
    buttonCell.showsBorderOnlyWhileMouseInside = true
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top