3

I have a borderless NSButton(more or less a NSTextField with an action) that I would like to behave like an "image-based" button, i.e. I would like the button text to change color when passed over with a mouse and when clicked. Is there an easy way to achieve that ?

Here is my button initialization context :

    NSButton* but =[[NSButton alloc] initWithFrame:NSMakeRect(5, 5, 125, 25)] ;
    [but setTitle:@"Do not show Again"];
    [but setButtonType:NSMomentaryLightButton]; //I figure it could be here
    [but setBezelStyle:NSHelpButtonBezelStyle];
    [but setBordered:NO];
    [but setAction:@selector(writeToUserDefaults)];
    [but setFont:[NSFont fontWithName:@"Arial" size:9.0]];
    [self.view addSubview:but];

Source that didn't work : Borderless NSButton Turns Gray

What are my solution (besides subclassing NSButton ?)

Community
  • 1
  • 1
Bertrand Caron
  • 2,525
  • 2
  • 22
  • 49
  • You could probably do it by subclassing `NSButtonCell`, though that is probably not what you want either. – JWWalker Nov 06 '13 at 06:33

1 Answers1

3

The solution is to use NSTrackingArea, from Apple documentation

An NSTrackingArea object defines a region of view that generates mouse-tracking and cursor-update events when the mouse is over that region.

In your situation you need to set up a tracking area with respect to the frame of your NSButton and change text color when you receive mouse tracking events.

- (void)awakeFromNib:(NSWindow *)newWindow 
{
    NSButton* but =[[NSButton alloc] initWithFrame:NSMakeRect(5, 5, 125, 25)] ;
    [but setTitle:@"Do not show Again"];
    [but setBezelStyle:NSHelpButtonBezelStyle];
    [but setBordered:NO];
    [but setAction:@selector(writeToUserDefaults)];
    [but setFont:[NSFont fontWithName:@"Arial" size:9.0]];
    [self.view addSubview:but];

    NSTrackingArea* trackingArea = [[NSTrackingArea alloc] initWithRect:[but frame] 
                                                                options:(NSTrackingInVisibleRect | NSTrackingEnabledDuringMouseDrag | NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways) 
                                                                  owner:self userInfo:nil];

[self.view addTrackingArea:trackingArea];
}

- (void) mouseEntered:(NSEvent*)theEvent {
    //Set text color
}

- (void) mouseExited:(NSEvent*)theEvent {
    //Reset text color
}
Suhas
  • 1,500
  • 11
  • 15
  • Thanks a lot for your detailed answer. What about the clicking part ? I couldn't find any tracking event related to mouseDown: or such. – Bertrand Caron Nov 06 '13 at 11:28
  • How is the button supposed to respond to mouse click? Is it different from what happens during mouse hover? – Suhas Nov 07 '13 at 02:05
  • I would have momentarily used a slightly darker color to show to the user that the window actually registered its clicking and did not spontaneously auto-closed. Do you think it's too much ? – Bertrand Caron Nov 07 '13 at 03:51
  • I think that it would be redundant, from what I understand you are also closing the window in the button's action which would be an indicator in itself that the click event has been registered. However you can use [but setButtonType:NSMomentaryLightButton] to show some sort of an indication. – Suhas Nov 07 '13 at 04:14
  • Remark dully noted aside , since my "button" is only a "label", `setButtonType:NSMomentaryLightButton]` does nothing (there is nothing to light). – Bertrand Caron Nov 07 '13 at 04:41
  • Hi, Bertrand. Have you found the solution to darker the color of the button title when clicking? Thanks. – Daniel Aug 05 '15 at 21:14