子类化 NSControl,IBAction 未在 Swift 中调用
Subclassing NSControl, IBAction is not called in Swift
我已经将一个 NSSlider 子类化,无论是否按下选项键,它的行为都不同。为此,我覆盖了 mouseDown 函数。它似乎完成了这项工作。
问题是,我注意到 ViewController 中连接的 @IBAction 仅在未按下选项键时触发(即,当 mouseDown 方法传递给 super 时)。为了允许@IBAction 执行,我缺少什么?
非常感谢
除了这个问题,欢迎对代码提出改进意见... :-)
乔什
class ViewController: NSViewController {
@IBOutlet weak var theSlider: MySlider!
@IBAction func moveSlider(sender: NSSlider) {
print(sender.floatValue) //works only with optionKey unpressed
}
}
class MySlider: NSSlider { //Implemented in another source file
@IBInspectable var multiplier: Float = 0.5
private var modifierKeys = NSEventModifierFlags.AlternateKeyMask
private var optionKeyPressed = false
private var previousSliderPosition: Float = 0.0
//MARK: Init with NSCoder
required init?(coder: NSCoder) {
super.init(coder: coder)
Swift.print("init Coder called")
self.continuous = true
NSEvent.addLocalMonitorForEventsMatchingMask(.FlagsChangedMask) { (theEvent) -> NSEvent? in
self.flagsChanged(theEvent)
return theEvent
}
}
//MARK: Mouse tracking
override func mouseDown(theEvent: NSEvent) {
if optionKeyPressed {
var keepOn = true
previousSliderPosition = self.floatValue * Float(self.bounds.width) / Float(self.maxValue)
while keepOn {
if let nextEvent = self.window?.nextEventMatchingMask(Int(NSEventMask.LeftMouseUpMask.rawValue) | Int(NSEventMask.LeftMouseDraggedMask.rawValue))
{
switch nextEvent.type
{
case .LeftMouseDragged:
let mouseInnerLocationX = Float(self.convertPoint(nextEvent.locationInWindow, fromView: self.superview).x)
let mouseDelta = mouseInnerLocationX - previousSliderPosition
let newSliderPosition = previousSliderPosition + (mouseDelta) * multiplier
self.floatValue = newSliderPosition * Float(self.maxValue) / Float(self.bounds.width)
break
case .LeftMouseUp:
keepOn = false
break
default:
break
}
}
}
} else {
super.mouseDown(theEvent)
}
}
//MARK: Option key handling
override func flagsChanged(theEvent: NSEvent) {
if (theEvent.modifierFlags.rawValue & NSEventModifierFlags.DeviceIndependentModifierFlagsMask.rawValue) == NSEventModifierFlags.AlternateKeyMask.rawValue {
optionKeyPressed = true
} else {
optionKeyPressed = false
}
}
}
如果您不调用 super.mouseDown
,您需要自己发送操作:
sendAction(action, to: target)
sendAction(_:to:)
、action
和 target
是 NSControl
的现有成员。
我已经将一个 NSSlider 子类化,无论是否按下选项键,它的行为都不同。为此,我覆盖了 mouseDown 函数。它似乎完成了这项工作。 问题是,我注意到 ViewController 中连接的 @IBAction 仅在未按下选项键时触发(即,当 mouseDown 方法传递给 super 时)。为了允许@IBAction 执行,我缺少什么?
非常感谢 除了这个问题,欢迎对代码提出改进意见... :-)
乔什
class ViewController: NSViewController {
@IBOutlet weak var theSlider: MySlider!
@IBAction func moveSlider(sender: NSSlider) {
print(sender.floatValue) //works only with optionKey unpressed
}
}
class MySlider: NSSlider { //Implemented in another source file
@IBInspectable var multiplier: Float = 0.5
private var modifierKeys = NSEventModifierFlags.AlternateKeyMask
private var optionKeyPressed = false
private var previousSliderPosition: Float = 0.0
//MARK: Init with NSCoder
required init?(coder: NSCoder) {
super.init(coder: coder)
Swift.print("init Coder called")
self.continuous = true
NSEvent.addLocalMonitorForEventsMatchingMask(.FlagsChangedMask) { (theEvent) -> NSEvent? in
self.flagsChanged(theEvent)
return theEvent
}
}
//MARK: Mouse tracking
override func mouseDown(theEvent: NSEvent) {
if optionKeyPressed {
var keepOn = true
previousSliderPosition = self.floatValue * Float(self.bounds.width) / Float(self.maxValue)
while keepOn {
if let nextEvent = self.window?.nextEventMatchingMask(Int(NSEventMask.LeftMouseUpMask.rawValue) | Int(NSEventMask.LeftMouseDraggedMask.rawValue))
{
switch nextEvent.type
{
case .LeftMouseDragged:
let mouseInnerLocationX = Float(self.convertPoint(nextEvent.locationInWindow, fromView: self.superview).x)
let mouseDelta = mouseInnerLocationX - previousSliderPosition
let newSliderPosition = previousSliderPosition + (mouseDelta) * multiplier
self.floatValue = newSliderPosition * Float(self.maxValue) / Float(self.bounds.width)
break
case .LeftMouseUp:
keepOn = false
break
default:
break
}
}
}
} else {
super.mouseDown(theEvent)
}
}
//MARK: Option key handling
override func flagsChanged(theEvent: NSEvent) {
if (theEvent.modifierFlags.rawValue & NSEventModifierFlags.DeviceIndependentModifierFlagsMask.rawValue) == NSEventModifierFlags.AlternateKeyMask.rawValue {
optionKeyPressed = true
} else {
optionKeyPressed = false
}
}
}
如果您不调用 super.mouseDown
,您需要自己发送操作:
sendAction(action, to: target)
sendAction(_:to:)
、action
和 target
是 NSControl
的现有成员。