[英]How to detect which NSTextField is clicked in Cocoa?
我有两个要在用户单击时突出显示的NSTextField
对象。
初始文本字段已在NSWindow
加载中突出显示。 我能够获得鼠标按下事件来单击文本字段,但是无法区分用户点击了哪个文本字段。
我尝试使用从NSEvent
对象获得的NSPoint
在文本字段上使用hitTest,但返回的NSView
为nil。 它返回的视图是窗口视图的视图,而不是文本字段。
class SettingsViewController: NSViewController {
private var sview: SettingsView?
override func viewDidLoad() {
initEvents()
}
override func loadView() {
if let settingsView = SettingsView.createFromNib() {
self.view = settingsView
self.sview = settingsView as? SettingsView
}
}
func initEvents() {
self.sview!.emailTextField.delegate = self
}
}
extension SettingsViewController: NSTextFieldDelegate, NSTextDelegate {
override func mouseDown(with event: NSEvent) {
self.log.debug("mouse down: \(event.buttonNumber), \(event.eventNumber), \(event.locationInWindow)")
// How to know which text field triggered this?
}
func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
self.log.debug("control delegate")
return false
}
func textField(_ textField: NSTextField, textView: NSTextView, shouldSelectCandidateAt index: Int) -> Bool {
self.log.debug("text field should select")
return true
}
func textShouldBeginEditing(_ textObject: NSText) -> Bool {
self.log.debug("text field should being editing")
return true
}
}
class SettingsView: NSView {
private let log = Logger()
private static var topLevelObjects: NSArray?
@IBOutlet weak var emailTextField: ASTextField!
@IBOutlet weak var passwordTextField: NSSecureTextField!
// ...
}
我将委托添加到仅一个文本字段。
self.sview!.emailTextField.delegate = self
但是,当我单击passwordTextField
,我也得到了鼠标单击事件。 为什么会这样呢?
如何区分NSTextField
鼠标单击并突出显示文本字段?
我尝试将NSTextField
子类化并添加单击处理程序,但是它不起作用。
class ASTextField: NSTextField {
private let log = Logger()
required init?(coder: NSCoder) {
super.init(coder: coder)
bootstrap()
}
override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
bootstrap()
}
override func awakeFromNib() {
super.awakeFromNib()
bootstrap()
}
func bootstrap() {
self.delegate = self
}
}
extension ASTextField: NSTextFieldDelegate {
override func mouseDown(with event: NSEvent) {
// This is not working
self.log.debug("mouse down")
super.mouseDown(with: event)
}
}
您改写的方法mouseDown(with)
不是NSTextFieldDelegate
或NSTextDelegate
协议的成员。 您NSViewController.mouseDown(with)
。
每当调用该方法时,单击的对象就是SettingsViewController
的视图。
要对您选择的文本字段做出反应,请使用已经具有的NSTextFieldDelegate .textField(_:textView:shouldSelectCandidateAt:)
。 textView
参数的值是所选的文本视图。
我更新了ASTextField
如下。
class ASTextField: NSTextField {
// ...
override func mouseDown(with event: NSEvent) {
self.sendAction(#selector(didClick(_:)), to: self)
super.mouseDown(with: event)
}
@objc func didClick(_ event: NSEvent) {
self.log.debug("did click")
}
}
在SettingsView
,我错过了调用super.layout()
,如果没有该调用,单击将无法进行,单击时其他文本字段也不会获得焦点。
class SettingsView: NSView {
// ...
override func layout() {
self.log.debug("layout method")
super.layout() // This is important
}
}
不需要NSTextField
委托方法。
如果您要查找的是单击(聚焦)文本字段时能够选择文本,则可以重写该类以简化您的任务,而不必担心从委托中找到被单击的字段。
对于一个NSView对象,当它获得焦点(即单击或制表)时,它将调用becomeFirstResponder
以便我们可以将其挂接到那里。
当NSTextField变为可编辑(或可选)时,它将获取可重用的“字段编辑器”,并在编辑期间将其覆盖在文本字段的顶部。 如果您的NSTextField具有焦点,则可以使用视图上的currentEditor()
调用获取此字段编辑器。
因此,一旦有了字段编辑器,就可以在编辑器上执行selectAll
以选择文本。
示例类:-
class AutoselectOnFocusTextField: NSTextField {
override func becomeFirstResponder() -> Bool {
guard super.becomeFirstResponder() else {
return false
}
if let editor = self.currentEditor() {
editor.perform(#selector(selectAll(_:)), with: self, afterDelay: 0)
}
return true
}
}
希望这可以帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.