如何给单选按钮着色?

问题描述

enter image description here

您可以看到 Apple 为单选按钮着色。我也想这样做。我似乎无法在情节提要的 Interface Builder 中找到更改颜色的选项。

至于这样做,以编程方式,我尝试启用图层 .wantsLayer = true,然后尝试通过 .layer?.borderColour = NSColor.systemBlue.cgColor 设置颜色并尝试使用 .layer?.backgroundColor = NSColor.systemRed.cgColor 和其他类似属性但无济于事。

同样,如何在 NSMenuItem 上的 NSPopUpButton添加颜色矩形?

enter image description here

解决方法

以下代码演示了一组通过子类化 NSButton 为 MacOS 制作的自定义单选按钮。它可以通过复制/粘贴到新添加的名为“main.swift”的文件并删除原始 AppDelegate 来在 Xcode swift 项目中运行。

import Cocoa

class CustomButton: NSButton {

var circleColor: NSColor!

override func draw(_ rect: NSRect) {
 let circle = NSBezierPath(ovalIn: bounds)
 switch(self.tag) {
  case 0:
   circleColor = NSColor.red
  case 1:
   circleColor = NSColor.green
  case 2:
   circleColor = NSColor.yellow
  case 3:
   circleColor = NSColor.orange
  default:
   break
 }
  circleColor.set()
  circle.fill()

  if(self.state) == .on {
   let dotRect = NSInsetRect(bounds,18.0,18.0);
   let dot = NSBezierPath (ovalIn:dotRect)
   let dotColor = NSColor.black
   dotColor.set()
   dot.fill()
  }
 }
}

class AppDelegate: NSObject,NSApplicationDelegate {
 var window: NSWindow!

@objc func radioGrpAction(_ sender:NSButton) {
 print("You selected: id = \(sender.tag)")
}

func buildMenu() {
let mainMenu = NSMenu()
NSApp.mainMenu = mainMenu
// **** App menu **** //
let appMenuItem = NSMenuItem()
mainMenu.addItem(appMenuItem)
let appMenu = NSMenu()
appMenuItem.submenu = appMenu
appMenu.addItem(withTitle: "Quit",action:#selector(NSApplication.terminate),keyEquivalent: "q")
}
    
func buildWnd() {
    
 let _wndW : CGFloat = 300
 let _wndH : CGFloat = 200
 window = NSWindow(contentRect:NSMakeRect(0,_wndW,_wndH),styleMask:[.titled,.closable,.miniaturizable],backing:.buffered,defer:false)
 window.center()
 window.title = "Radio Button Group"
 window.makeKeyAndOrderFront(window)

// === Radio Grp Box === //
 let grpBox = NSBox(frame: NSMakeRect( 50,_wndH - 100,150,60))
 grpBox.title = "Radio Group"
 window.contentView!.addSubview (grpBox)
 // === Radio Horizontal Grid === //
 let _btnW : CGFloat = 24
 let _btnH : CGFloat = 24
 let _left : CGFloat = 10 // left margin first button
 let _YOffset : CGFloat = 5 // 0,0 at left,bottom of group box
 let _spacing : CGFloat = 5 // spacing between buttons

 for x in stride(from:0,through:3,by:1) {
 let _XOffset = _left + CGFloat(x)*(_btnW + _spacing)
 let btn = CustomButton(frame:NSMakeRect(_XOffset,_YOffset,_btnW,_btnH))
 btn.setButtonType(.radio)
 btn.tag = x
 if(x == 0){btn.state = .on}
 btn.action = #selector(self.radioGrpAction(_:))
 grpBox.contentView!.addSubview(btn)
}

// === Quit btn === //
 let quitBtn = NSButton (frame:NSMakeRect( _wndW - 50,10,40,40 ))
 quitBtn.bezelStyle = .circular
 quitBtn.title = "Q"
 quitBtn.action = #selector(NSApplication.terminate)
 window.contentView!.addSubview(quitBtn)
}
 
func applicationDidFinishLaunching(_ notification: Notification) {
 buildMenu()
 buildWnd()
}

func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
 return true
}

}
let appDelegate = AppDelegate()

// ***** main.swift ***** //
let app = NSApplication.shared
app.setActivationPolicy(.regular)
app.delegate = appDelegate
app.activate(ignoringOtherApps:true)
app.run()


radioGrp

,

好的,但对于 AppKit:

import Cocoa
import AppKit

extension NSView {
    
    func centerX(inView view: NSView,constant: CGFloat = 0) {
        translatesAutoresizingMaskIntoConstraints = false
        centerXAnchor.constraint(equalTo: view.centerXAnchor,constant: constant).isActive = true
    }
    
    func centerY(inView view: NSView,constant: CGFloat = 0) {
        translatesAutoresizingMaskIntoConstraints = false
        centerYAnchor.constraint(equalTo: view.centerYAnchor,constant: constant).isActive = true
    }
    
    func setDimensions(height: CGFloat,width: CGFloat) {
        translatesAutoresizingMaskIntoConstraints = false
        heightAnchor.constraint(equalToConstant: height).isActive = true
        widthAnchor.constraint(equalToConstant: width).isActive = true
    }
}

class CustomRadioButton: NSView {
    
    private let containerSize: CGFloat = 60.0
    private let selectorSize: CGFloat = 20.0
    
    var containerColor: NSColor = .blue
    var selectorColor: NSColor = .red
    
    var selected: Bool = true {
        didSet {
            selectorView.isHidden = !selected
        }
    }
    
    private lazy var containerView: NSView = {
        
        let view = NSView()
        
        view.wantsLayer = true
        
        view.layer?.backgroundColor = containerColor.cgColor
        
        return view
        
    }()
    
    private lazy var selectorView: NSView = {
        
        let view = NSView()
        view.wantsLayer = true
        
        view.layer?.backgroundColor = selectorColor.cgColor
        
        return view
        
    }()
    
    override init(frame: CGRect) {
        super.init(frame: CGRect(x: 0,y: 0,width: containerSize,height: containerSize))
        
        configureUI()
    
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    
    
    private func configureUI() {
        addSubview(containerView)
        containerView.setDimensions(height: containerSize,width: containerSize)
        containerView.layer?.cornerRadius = containerSize / 2
        containerView.centerX(inView: self)
        containerView.centerY(inView: self)
        
        addSubview(selectorView)
        
        selectorView.setDimensions(height: selectorSize,width: selectorSize)
        selectorView.layer?.cornerRadius = selectorSize / 2
        selectorView.centerY(inView: containerView)
        selectorView.centerX(inView: containerView)
        
    }
    
    
}

let selector = CustomRadioButton()

selector.selected = false