31
votes

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

12 Answers

14
votes

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.

41
votes

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.

16
votes

Here is another possible way to do this:

    let button = NSButton()
    button.title = ""
    button.bezelStyle = .texturedSquare
    button.isBordered = false //Important
    button.wantsLayer = true
    button.layer?.backgroundColor = NSColor.red.cgColor
13
votes

If anyone face problem for storyboard setup then for reference check: You can set properties directly to NSButton as shown below

: enter image description here

Result :
enter image description here

9
votes

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:

https://github.com/OskarGroth/FlatButton

FlatButton for macOS

3
votes

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.

  1. Find the button in interfaceBuilder and click on it.
  2. 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.
  3. With the NSButtonCell selected, Click on the Identity-Inspector.
  4. In the Identity-inspector look for the section called User Defined Runtime Attributes
  5. Click on the little plus (+) sign to add a value. The Value will show to have 3 properties. (A) keyPath (B) Type (C) Value
  6. 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.

1
votes

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];
}
1
votes

In Swift you can do like this:

(button.cell as! NSButtonCell).isBordered = false
(button.cell as! NSButtonCell).backgroundColor = .white
0
votes

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

0
votes

If anybody is still looking at this. This code works in Swift 5...

button.layer?.backgroundColor = NSColor.green.cgColor

... you have to set needsLayer or add a layer in the nib first. It works with borders as well.

-1
votes

you can choose your own color by clicking "Other..." option from color paletteUse "#colorLiteral" to select the color from the GUI color palette.

Button.layer?.backgroundColor = #colorLiteral(red: 0, green: 0.4797514677, blue: 0.9984372258, alpha: 1)

see image

-11
votes

UIElement(Element is of anything Like Button,view....)

UIElement *varname;

[varname setBackgroundColor:[UIColor colorWithRed:0.8 green:0.8 blue:0.6 alpha:1.0]];

eg: UIButton *pButton;

[pButton setBackgroundColor:[UIColor colorWithRed:0.8 green:0.8 blue:0.6 alpha:1.0]];