I have an NSButton in a mac application whose colour I'd like to change programatically but nothing I tried seems to work. I tried to create an output on the NSButtonCell and set the background color there but that didn't work either. Any code snippets would be helpful.
12 Answers
The standard Aqua (pill-shaped) buttons are drawn by the system. They don't have a background color as such. In fact, they are composed of images that Cocoa stitches together to make a coherent button image. So Cocoa can't recolor the images to your liking. Only the default button (the one with Return set as its key equivalent) will have a blue pulsing background.
What it sounds like you want to do will involve subclassing NSButtonCell
and doing your own drawing. If you wanted to recolor the button images to get the effect you want, you can use the excellent Theme Park utility to extract copies of Apple's button images and use those. I'll admit to having done this myself in order to "steal" certain interface elements that aren't otherwise accessible, such as the scrollers from iTunes.
Assuming everything is hooked up in IB for your borderless button.
// *.h file
IBOutlet NSButton* myButton;
// *.m file
[[myButton cell] setBackgroundColor:[NSColor redColor]];
Note from the setBackgroundColor documentation:
"The background color is used only when drawing borderless buttons."
If this won't do it for you then you'll need to override NSButton and implement the drawing yourself.
Good Luck.
I've created a NSButton
subclass called FlatButton
that makes it super-easy to change button background color, text color, icon color, borders and other types of styling, from Interface Builder:
Mark's answer is correct. But if doing it by code will be messy for you, then another way to do it is to set it directly in interface builder.
- Find the button in interfaceBuilder and click on it.
- On the object browser section of interface builder you will see the button that you clicked on has a dropdown disclosure icon. Click on it. It will then show you the NSButtonCell of the NSButton. Click on it.
- With the NSButtonCell selected, Click on the Identity-Inspector.
- In the Identity-inspector look for the section called
User Defined Runtime Attributes
- Click on the little plus (+) sign to add a value. The Value will show to have 3 properties. (A) keyPath (B) Type (C) Value
- Change the keyPath to:
backgroundColor
. Change the type to:Color
. Change the value to: what ever color you want (a color picker will be displayed)
Done.
One method is to create a view behind the button and set the colour of that. This creates the view with the same frame and the puts the button on top of the view. I use a tag on the button to make sure we only add the view once, so the method can be called repeatedly when drawing the UI.
I've included my code for setting the text colour.
Change the colour and alpha as desired:
NSColor *colour = [NSColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:0.5] ;
[self styleButton:button colour:colour] ;
-(void) styleButton:(NSButton *)button colour:(NSColor *)colour {
[self setButton:button fontColor:[NSColor whiteColor]];
if(button.tag == 9901) return ;
button.bezelStyle = NSBezelStyleTexturedSquare ;
[button setBordered:NO];
NSView *b2 = [[NSView alloc] initWithFrame:button.frame] ;
[button.superview addSubview:b2] ;
b2.layer.backgroundColor = colour.CGColor;
[button removeFromSuperview];
[b2.superview addSubview:button];
button.tag = 9901 ;
}
-(void) setButton:(NSButton *)button fontColor:(NSColor *)color {
NSMutableAttributedString *colorTitle = [[NSMutableAttributedString alloc] initWithAttributedString:[button attributedTitle]];
[colorTitle addAttribute:NSForegroundColorAttributeName value:color range:NSMakeRange(0, button.attributedTitle.length)];
[button setAttributedTitle:colorTitle];
}
Thanks for these great answers. I've compiled an NSButton subclass that makes it easy to set background color, border attributes (color, width, corners), and title attributes (color, font).
Feel free to use: https://github.com/philfung/osx-dudley/blob/master/DudNSButton.swift