如何从 NSTextField 的字段编辑器中拦截击键?
How to intercept keystrokes from within the field editor of an NSTextField?
简介
当我的自定义 NSTextField
位于 "text editing mode" 并且 field editor
已作为 firstResponder
放在其前面时,我不再通过 [=15 获得击键=].我知道击键现在正在通过 field editor
进行路由。网上大部分推荐都是在自定义的delegate中覆盖下面的方法NSTextField
:
control(_:textView:doCommandBySelector:)
我确实重写了这个方法,但是好像没有被调用?请参阅下面的代码:
class FocusDelegate: NSObject, NSTextFieldDelegate{
func control(control: NSControl, textView: NSTextView, doCommandBySelector commandSelector: Selector) -> Bool {
println("FocusDelegate")
if commandSelector == Selector("cancelOperation:"){
println("cancelOperation")
control.abortEditing()
return true
}
return false
}
}
我唯一要做的另一件事是将我的自定义 NSTextField
的委托设置为上面 class 的一个实例。我还尝试将上面的方法直接放入自定义 NSTextField
class - 它不会导致任何错误,但也不会被调用。
问题
- 我在上面让委托调用工作时遗漏了什么?
- 除了创建我自己的自定义字段编辑器之外,这是唯一的方法吗?
textDidChange(notification: NSNotification)
不能被询问以产生按下的键吗?
- 在使用
control(_:textView:doCommandBySelector:)
委托方法时,如何捕获 NOT 具有标准键绑定的键的按下。特别是,我想拦截不映射到任何标准选择器的组合键 "shift+enter" 。 (隐含的问题:你只能映射到 NSResponder 中的标准按键操作方法吗?)
我相信我已经更加清楚地了解 NSTextField
其代表及其 fieldEditor 及其代表的工作方式。是的,每个人都有自己的代表,NSTextField
自动设置为 fieldEditor
.
的代表
我正在向主持人添加委托 NSTextField
。当 fieldEditor
是 firstResponder
时,这将 NOT 被调用,这是我所关心的。这也不是上述场景的重要代表。
似乎有用的是使 NSTextField
符合 NSTextViewDelegate
协议并特别覆盖方法:
func textView(textView: NSTextView, shouldChangeTextInRange affectedCharRange: NSRange, replacementString: String) -> Bool
捕获各种按键。
textDidChange(notification: NSNotification)
中的通知在这种情况下没有用,因为它是在 按键之后报告的。
在 textView:shouldChangeTextInRange:replacementString:
中截获按下的键并不理想,因为它被调用的时间很晚,例如,当用户从剪贴板粘贴时也会被调用。
一个可能更简洁的方法是截取 textView:doCommandBySelector:
,它会被各种特殊键调用,例如制表符、光标、return 和回车,然后您将获得特定的选择器让您确定调用了哪个特殊键。
但是,对于某些键,例如Return(CR
)和Enter(ETX
),您无法区分它们,因为它们使用相同的“insertNewline :" 选择器。
在这种情况下,您可以检查当前处理的事件是否是按键事件,如果是,请检查它是哪个键。
这是一个快速测试代码,可让您监控选择器名称和涉及的键码:
-(BOOL)textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector
{
NSEvent *ev = self.view.window.currentEvent;
NSLog (@"selector: %s, key: %d", commandSelector, (int)ev.keyCode);
return NO;
}
简介
当我的自定义 NSTextField
位于 "text editing mode" 并且 field editor
已作为 firstResponder
放在其前面时,我不再通过 [=15 获得击键=].我知道击键现在正在通过 field editor
进行路由。网上大部分推荐都是在自定义的delegate中覆盖下面的方法NSTextField
:
control(_:textView:doCommandBySelector:)
我确实重写了这个方法,但是好像没有被调用?请参阅下面的代码:
class FocusDelegate: NSObject, NSTextFieldDelegate{
func control(control: NSControl, textView: NSTextView, doCommandBySelector commandSelector: Selector) -> Bool {
println("FocusDelegate")
if commandSelector == Selector("cancelOperation:"){
println("cancelOperation")
control.abortEditing()
return true
}
return false
}
}
我唯一要做的另一件事是将我的自定义 NSTextField
的委托设置为上面 class 的一个实例。我还尝试将上面的方法直接放入自定义 NSTextField
class - 它不会导致任何错误,但也不会被调用。
问题
- 我在上面让委托调用工作时遗漏了什么?
- 除了创建我自己的自定义字段编辑器之外,这是唯一的方法吗?
textDidChange(notification: NSNotification)
不能被询问以产生按下的键吗? - 在使用
control(_:textView:doCommandBySelector:)
委托方法时,如何捕获 NOT 具有标准键绑定的键的按下。特别是,我想拦截不映射到任何标准选择器的组合键 "shift+enter" 。 (隐含的问题:你只能映射到 NSResponder 中的标准按键操作方法吗?)
我相信我已经更加清楚地了解 NSTextField
其代表及其 fieldEditor 及其代表的工作方式。是的,每个人都有自己的代表,NSTextField
自动设置为 fieldEditor
.
我正在向主持人添加委托 NSTextField
。当 fieldEditor
是 firstResponder
时,这将 NOT 被调用,这是我所关心的。这也不是上述场景的重要代表。
似乎有用的是使 NSTextField
符合 NSTextViewDelegate
协议并特别覆盖方法:
func textView(textView: NSTextView, shouldChangeTextInRange affectedCharRange: NSRange, replacementString: String) -> Bool
捕获各种按键。
textDidChange(notification: NSNotification)
中的通知在这种情况下没有用,因为它是在 按键之后报告的。
在 textView:shouldChangeTextInRange:replacementString:
中截获按下的键并不理想,因为它被调用的时间很晚,例如,当用户从剪贴板粘贴时也会被调用。
一个可能更简洁的方法是截取 textView:doCommandBySelector:
,它会被各种特殊键调用,例如制表符、光标、return 和回车,然后您将获得特定的选择器让您确定调用了哪个特殊键。
但是,对于某些键,例如Return(CR
)和Enter(ETX
),您无法区分它们,因为它们使用相同的“insertNewline :" 选择器。
在这种情况下,您可以检查当前处理的事件是否是按键事件,如果是,请检查它是哪个键。
这是一个快速测试代码,可让您监控选择器名称和涉及的键码:
-(BOOL)textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector
{
NSEvent *ev = self.view.window.currentEvent;
NSLog (@"selector: %s, key: %d", commandSelector, (int)ev.keyCode);
return NO;
}