[英]How to detect which NSTextField is clicked in Cocoa?
I have two NSTextField
objects which I want to highlight when user clicks on it. 我有两个要在用户单击时突出显示的
NSTextField
对象。
The initial text field is already highlighted on NSWindow
load. 初始文本字段已在
NSWindow
加载中突出显示。 I am able to get mouse down event for text field click, but unable to distinguish which textfield did the user tapped. 我能够获得鼠标按下事件来单击文本字段,但是无法区分用户点击了哪个文本字段。
I tried using hitTest on the text field using the NSPoint
obtained from the NSEvent
object, but the NSView
returned is nil. 我尝试使用从
NSEvent
对象获得的NSPoint
在文本字段上使用hitTest,但返回的NSView
为nil。 The view it returns is that of the window's view and not that text field. 它返回的视图是窗口视图的视图,而不是文本字段。
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!
// ...
}
I am adding delegate to only one text field. 我将委托添加到仅一个文本字段。
self.sview!.emailTextField.delegate = self
But when I click on the passwordTextField
, I am getting the mouse click event as well. 但是,当我单击
passwordTextField
,我也得到了鼠标单击事件。 Why is this happening? 为什么会这样呢?
How to distinguish NSTextField
mouse click and highlight the text field? 如何区分
NSTextField
鼠标单击并突出显示文本字段?
I tried subclassing NSTextField
and adding click handler, but it is not working. 我尝试将
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)
}
}
The method you overwrote, mouseDown(with)
, isn't a member of the NSTextFieldDelegate
or NSTextDelegate
protocols. 您改写的方法
mouseDown(with)
不是NSTextFieldDelegate
或NSTextDelegate
协议的成员。 You overwrote NSViewController.mouseDown(with)
. 您
NSViewController.mouseDown(with)
。
Whenever that method is called, the thing that was clicked is your SettingsViewController
's view. 每当调用该方法时,单击的对象就是
SettingsViewController
的视图。
To react to your textfield being selected, you use NSTextFieldDelegate .textField(_:textView:shouldSelectCandidateAt:)
, which you already have. 要对您选择的文本字段做出反应,请使用已经具有的
NSTextFieldDelegate .textField(_:textView:shouldSelectCandidateAt:)
。 The value of the textView
parameter is the text view that was selected. textView
参数的值是所选的文本视图。
I updated the ASTextField
as below. 我更新了
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")
}
}
In the SettingsView
, I missed calling super.layout()
, without which the click won't work, nor the other text field will get focus when clicked. 在
SettingsView
,我错过了调用super.layout()
,如果没有该调用,单击将无法进行,单击时其他文本字段也不会获得焦点。
class SettingsView: NSView {
// ...
override func layout() {
self.log.debug("layout method")
super.layout() // This is important
}
}
NSTextField
delegate methods are not required. 不需要
NSTextField
委托方法。
If what you're looking for is to be able to select the text when you click (focus) the text field, you can override the class to simplify your task and you won't have to worry about locating the clicked field from the delegate. 如果您要查找的是单击(聚焦)文本字段时能够选择文本,则可以重写该类以简化您的任务,而不必担心从委托中找到被单击的字段。
For an NSView object, when it gets focus (ie. clicking or tabbing) it will call becomeFirstResponder
so we can hook in there. 对于一个NSView对象,当它获得焦点(即单击或制表)时,它将调用
becomeFirstResponder
以便我们可以将其挂接到那里。
When an NSTextField becomes editable (or selectable) it grabs a reusable 'field editor' and overlays it on top of your text field during the editing. 当NSTextField变为可编辑(或可选)时,它将获取可重用的“字段编辑器”,并在编辑期间将其覆盖在文本字段的顶部。 If your NSTextField has focus, you can grab this field editor using the
currentEditor()
call on the view. 如果您的NSTextField具有焦点,则可以使用视图上的
currentEditor()
调用获取此字段编辑器。
So, once you have the field editor, you can perform selectAll
on the editor to select the text. 因此,一旦有了字段编辑器,就可以在编辑器上执行
selectAll
以选择文本。
Example class :- 示例类:-
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
}
}
Hope this helps! 希望这可以帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.