简体   繁体   中英

Set color of NSButton programmatically swift

I generate some NSButtons programmatically with this code:

for i in 1...height {
        for j in 1...width {
            var but = NSButton(frame: NSRect(x: x, y: y + 78, width: 30, height: 30))
            but.tag = k
            but.title = ""
            but.action = Selector("buttonPressed:")
            but.target = self
            but.bezelStyle = NSBezelStyle(rawValue: 6)!
            but.layer?.backgroundColor = NSColor.blackColor().CGColor

            var ges = NSClickGestureRecognizer(target: self, action: Selector("addFlag:"))
            ges.buttonMask = 0x2
            ges.numberOfClicksRequired = 1
            but.addGestureRecognizer(ges)

            ar.append(but)
            self.view.addSubview(but)
            x += 30
            k++
        }
        y += 30
        x = 0
    }

And I need to set the background color of all buttons to gray or black (randomly). I have no idea how to get or set the NSButton background color. I'm quite new to swift programming and I don't really know obj-c, so if you'll write it on swift, I'll really appreciate it!

I'm doing it with this code

final class MyButton: NSButton {
    override func awakeFromNib() {
        let layer = CALayer()
        layer.backgroundColor = CGColorCreateGenericRGB(59.0/255, 52.0/255.0, 152.0/255.0, 1.0)
        self.wantsLayer = true
        self.layer = layer
    }
}

I read throgh the NSButton reference guide, And it seems that the only way to change it it changing the image. But I have gotten a way to create an image using a colour. Add this extionsion at the top of your class file

extension NSImage {
class func swatchWithColor(color: NSColor, size: NSSize) -> NSImage {
    let image = NSImage(size: size)
    image.lockFocus()
    color.drawSwatchInRect(NSMakeRect(0, 0, size.width, size.height))
    image.unlockFocus()
    return image
   }
}

This will allow us to later create NSImage's using a UIColour. Lastly, When you want to create your button, Set the image using the extension we made.

 myButton.image = NSImage.swatchWithColor( NSColor.blackColor(), size: NSMakeSize(100, 100) )

For the size parameter set it to your button's size.

UPDATE* If you want to randomly choose the colour you can do this..

 var randomIndex = arc4random_uniform(2) + 1 //Creates a random number between 1 and 2  
 var colour = NSColor() //Empty colour

    if randomIndex == 1 {

        //If the random number is one then the colour is black
        colour = NSColor.blackColor()
    }

    else {

        //Else if it's not one it's grey
        colour = NSColor.grayColor()
    }

    //set the button's image to the new colour
    myButton.image = NSImage.swatchWithColor(colour, size: //My button size)

To get the size go to your storyboard, click on your button and go to the ruler tab. There it shows your button's size.

The bad news is that there is, IMHO, no good way of colouring buttons; they all have advantages and drawbacks. For everyone who, like me, felt curious about colouring buttons under Yosemite I have written what may not be the ultimate guide to colouring buttons, but definitely a strong contender:

http://www.extelligentcocoa.org/colouring-buttons/

This covers all styles of buttons, and has screenshots for almost any combination, using

  • backgroundColor
  • drawRect
  • cell backgroundColor
  • monochrome layerEffect
  • whiteBalance Adjust layerEffect
  • images set in IB
  • subclassing NSButton and adding images depending on the button state

If anyone can think of another way of colouring buttons, I'm interested to hear of it!

Okay, here is what I did when I needed to change the look of a button: subclass it.

//
//  LSButtonColor.swift
//
//  Created by Lloyd Sargent on 8/26/16.
//  Copyright © 2016 Canna Software. All rights reserved.
//  License: Permission is hereby granted, free of charge, to any 
//           person obtaining a copy of this software and associated
//           documentation files (the “Software”), to deal in the 
//           Software without restriction, including without
//           limitation the rights to use, copy, modify, merge, 
//           publish, distribute, sublicense, and/or sell copies of 
//           the Software, and to permit persons to whom the Software 
//           is furnished to do so, subject to the following
//           conditions:
//           
//           The above copyright notice and this permission notice
//           shall be included in all copies or substantial portions
//           of the Software.
//
//           THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF
//           ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
//           TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
//           PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
//           SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
//           CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
//           OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
//           IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
//           DEALINGS IN THE SOFTWARE.
//

import Cocoa

class LSButtonColor: NSButton {

fileprivate struct AssociatedKeys {
    static var variableDictionary = "ls_variableDictionary"
}

fileprivate var variableDictionary: [String:AnyObject]! {
    get {
        var localVariableDictionary = objc_getAssociatedObject(self, &AssociatedKeys.variableDictionary) as! [String:AnyObject]!
        if localVariableDictionary == nil {
            localVariableDictionary = [String:AnyObject]()
            objc_setAssociatedObject(self, &AssociatedKeys.variableDictionary, localVariableDictionary, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        return localVariableDictionary
    }
    set(updatedDictionary) {
        objc_setAssociatedObject(self, &AssociatedKeys.variableDictionary, updatedDictionary, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    }
}

var backgroundColor: NSColor! {
    get {
        return variableDictionary["backgroundColor"] as? NSColor
    }
    set(newBackgroundColor) {
        var localVariableDictionary = variableDictionary
        localVariableDictionary?["backgroundColor"] = newBackgroundColor
        variableDictionary = localVariableDictionary
    }
}

var altBackgroundColor: NSColor! {
    get {
        return variableDictionary["altBackgroundColor"] as? NSColor
    }
    set(newAltBackgroundColor) {
        var localVariableDictionary = variableDictionary
        localVariableDictionary?["altBackgroundColor"] = newAltBackgroundColor
        variableDictionary = localVariableDictionary
    }
}

var borderColor: NSColor! {
    get {
        return variableDictionary["borderColor"] as? NSColor
    }
    set(newBorderColor) {
        var localVariableDictionary = variableDictionary
        localVariableDictionary?["borderColor"] = newBorderColor
        variableDictionary = localVariableDictionary

        self.layer?.borderColor = newBorderColor.cgColor
    }
}

var cornerRadius: CGFloat {
    get {
        return variableDictionary["cornerRadius"] as! CGFloat
    }
    set(newCornerRadius) {
        var localVariableDictionary = variableDictionary
        localVariableDictionary?["cornerRadius"] = newCornerRadius as AnyObject?
        variableDictionary = localVariableDictionary

        self.layer?.cornerRadius = newCornerRadius
    }
}

var borderWidth: CGFloat {
    get {
        return variableDictionary["borderWidth"] as! CGFloat
    }
    set(newBorderWidth) {
        var localVariableDictionary = variableDictionary
        localVariableDictionary?["borderWidth"] = newBorderWidth as AnyObject?
        variableDictionary = localVariableDictionary

        self.layer?.borderWidth = newBorderWidth
    }
}

override func draw(_ dirtyRect: NSRect) {
    super.draw(dirtyRect)

    // Drawing code here.
    if self.isHighlighted {
        if self.layer != nil {
            self.layer?.backgroundColor = self.altBackgroundColor.cgColor
        }
    }
    else {
        if self.layer != nil {
            self.layer?.backgroundColor = self.backgroundColor.cgColor
        }
    }
  }
}

Okay, the first thing you might be puzzling over is the objc_getAssociatedObject - originally I did this as a category and it is an easy-peasy way of adding variables to categorys (everyone says you can't do it, but everyone doesn't realize that, yes, you can - it's just not obvious).

Unfortunately, I ran into some issues, so I just made it a class - and didn't bother to take out the associated object (why mess with success?)

Anyway, you should be able to pull out the relevant code to change the background of any button.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM