NSSlider 自定义子类 - 如何保持旋钮位置和用户交互之间的 link?
NSSlider custom subclass - how to maintain the link between the knob position and user interaction?
正在尝试创建自定义 NSSlider
。覆盖 NSSliderCell
的 drawKnob()
方法会改变旋钮的外观,但这样做会以某种方式断开旋钮位置和用户与滑块交互之间的 link。
在经常引用的 objective C 示例 (https://github.com/lucasderraugh/LADSlider) 中,当您覆盖 drawKnob()
时,您似乎需要显式处理 startTracking
方法,但我还没有找到适合我的解决方案 - 目前我只是将单元格的 startTracking 'at' 属性 设置为滑块的当前值,但不确定正确的方法是什么。
相当多的示例在单元格的自定义初始化程序中包含一个 NSCoder 参数 - 我不明白为什么,但这可能与确保旋钮显示和实际滑块值之间的连接有关?
import Cocoa
class ViewController: NSViewController {
var seekSlider = NSSlider()
var seekSliderCell = SeekSliderCell()
override func viewDidLoad() {
super.viewDidLoad()
seekSlider = NSSlider(target: self, action: #selector(self.seek(_:)))
seekSlider.cell = seekSliderCell
seekSlider.cell?.target = self
seekSlider.cell?.action = #selector(self.seek(_:))
seekSlider.isEnabled = true
seekSlider.isContinuous = true
view.addSubview(seekSlider)
}
@objc func seek(_ sender: NSObject) {
let val = seekSlider.cell?.floatValue
let point = NSPoint(x: Double(val!), y: 0.0)
seekSlider.cell?.startTracking(at: point, in: self.seekSlider)
}
}
class SeekSliderCell: NSSliderCell {
// required init(coder aDecoder: NSCoder) {
// super.init(coder: aDecoder)
// }
override func drawKnob() {
let frame = NSRect(x: 0.0, y: 6.0, width: 20.0, height: 10.0)
let c = NSColor(red: 0.9, green: 0.0, blue: 0.6, alpha: 1.0)
c.setFill()
NSBezierPath.init(roundedRect: frame, xRadius: 3, yRadius: 3).fill()
}
override func startTracking(at startPoint: NSPoint, in controlView: NSView) -> Bool {
return true
}
}
drawKnob()
的文档指出:
Special Considerations
If you create a subclass of NSSliderCell, don’t override this method. Override drawKnob(_:) instead.
而不是
func drawKnob()
覆盖
func drawKnob(_ knobRect: NSRect)
示例:
class ViewController: NSViewController {
var seekSlider = NSSlider()
var seekSliderCell = SeekSliderCell()
override func viewDidLoad() {
super.viewDidLoad()
seekSlider = NSSlider(target: self, action: #selector(self.seek(_:)))
seekSlider.cell = seekSliderCell
seekSlider.cell?.target = self
seekSlider.cell?.action = #selector(self.seek(_:))
seekSlider.isEnabled = true
seekSlider.isContinuous = true
view.addSubview(seekSlider)
}
@objc func seek(_ sender: NSObject) {
let val = seekSlider.cell?.floatValue
print("\(String(describing: val))")
}
}
class SeekSliderCell: NSSliderCell {
override func drawKnob(_ knobRect: NSRect) {
var frame = NSRect(x: 0.0, y: 6.0, width: 20.0, height: 10.0)
frame.origin.x = knobRect.origin.x + (knobRect.size.width - frame.size.width) / 2
frame.origin.y = knobRect.origin.y + (knobRect.size.height - frame.size.height) / 2
let c = NSColor(red: 0.9, green: 0.0, blue: 0.6, alpha: 1.0)
c.setFill()
NSBezierPath.init(roundedRect: frame, xRadius: 3, yRadius: 3).fill()
}
}
正在尝试创建自定义 NSSlider
。覆盖 NSSliderCell
的 drawKnob()
方法会改变旋钮的外观,但这样做会以某种方式断开旋钮位置和用户与滑块交互之间的 link。
在经常引用的 objective C 示例 (https://github.com/lucasderraugh/LADSlider) 中,当您覆盖 drawKnob()
时,您似乎需要显式处理 startTracking
方法,但我还没有找到适合我的解决方案 - 目前我只是将单元格的 startTracking 'at' 属性 设置为滑块的当前值,但不确定正确的方法是什么。
相当多的示例在单元格的自定义初始化程序中包含一个 NSCoder 参数 - 我不明白为什么,但这可能与确保旋钮显示和实际滑块值之间的连接有关?
import Cocoa
class ViewController: NSViewController {
var seekSlider = NSSlider()
var seekSliderCell = SeekSliderCell()
override func viewDidLoad() {
super.viewDidLoad()
seekSlider = NSSlider(target: self, action: #selector(self.seek(_:)))
seekSlider.cell = seekSliderCell
seekSlider.cell?.target = self
seekSlider.cell?.action = #selector(self.seek(_:))
seekSlider.isEnabled = true
seekSlider.isContinuous = true
view.addSubview(seekSlider)
}
@objc func seek(_ sender: NSObject) {
let val = seekSlider.cell?.floatValue
let point = NSPoint(x: Double(val!), y: 0.0)
seekSlider.cell?.startTracking(at: point, in: self.seekSlider)
}
}
class SeekSliderCell: NSSliderCell {
// required init(coder aDecoder: NSCoder) {
// super.init(coder: aDecoder)
// }
override func drawKnob() {
let frame = NSRect(x: 0.0, y: 6.0, width: 20.0, height: 10.0)
let c = NSColor(red: 0.9, green: 0.0, blue: 0.6, alpha: 1.0)
c.setFill()
NSBezierPath.init(roundedRect: frame, xRadius: 3, yRadius: 3).fill()
}
override func startTracking(at startPoint: NSPoint, in controlView: NSView) -> Bool {
return true
}
}
drawKnob()
的文档指出:
Special Considerations If you create a subclass of NSSliderCell, don’t override this method. Override drawKnob(_:) instead.
而不是
func drawKnob()
覆盖
func drawKnob(_ knobRect: NSRect)
示例:
class ViewController: NSViewController {
var seekSlider = NSSlider()
var seekSliderCell = SeekSliderCell()
override func viewDidLoad() {
super.viewDidLoad()
seekSlider = NSSlider(target: self, action: #selector(self.seek(_:)))
seekSlider.cell = seekSliderCell
seekSlider.cell?.target = self
seekSlider.cell?.action = #selector(self.seek(_:))
seekSlider.isEnabled = true
seekSlider.isContinuous = true
view.addSubview(seekSlider)
}
@objc func seek(_ sender: NSObject) {
let val = seekSlider.cell?.floatValue
print("\(String(describing: val))")
}
}
class SeekSliderCell: NSSliderCell {
override func drawKnob(_ knobRect: NSRect) {
var frame = NSRect(x: 0.0, y: 6.0, width: 20.0, height: 10.0)
frame.origin.x = knobRect.origin.x + (knobRect.size.width - frame.size.width) / 2
frame.origin.y = knobRect.origin.y + (knobRect.size.height - frame.size.height) / 2
let c = NSColor(red: 0.9, green: 0.0, blue: 0.6, alpha: 1.0)
c.setFill()
NSBezierPath.init(roundedRect: frame, xRadius: 3, yRadius: 3).fill()
}
}