NSButtonCell hover image, transparent background on click?
-
02-06-2021 - |
문제
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 :
On Hover :
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:
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
}