NSResponder定义了许多与键盘操作相关的操作,如moveUp:、moveUpAndModifySelection:和moveToBeginningOfLine:。除按下修饰符键(e.x )未触发的动作外。moveUp:只是Up箭头键),我无法在自定义NSView上调用任何操作。
下面是设置:
Custom View添加到主窗口。NSView STView。STView只会重写acceptsFirstResponder以返回YES。在这个设置中,我的STView实例将正确地接收所有键盘事件(包括那些在performKeyEquivalent:和keyDown:中都带有像Ctl-A这样的修饰符的事件,正如所期望的那样。(这两种方法都被注释掉,以供下面讨论。)
如果我为moveUp:提供了一个实现(如NSResponder中定义的那样),那么当用户按下Up箭头键时,将正确调用moveUp:。
令人困惑的是,每当使用修饰符键按下moveUp:箭头键时,都会调用Up。当持有修饰符键(e.x.:Ctl-Up)时,我希望调用适当的键盘操作方法。
例如:
Ctl-Up -> moveUp: (预期:scrollPageUp:)Alt-Up -> moveUp: (预期:moveToBeginningOfParagraph:)Shift-Up -> moveUp: (预期:moveUpAndModifySelection:)Command-Up -> moveUp: (预期:moveToBeginningOfDocument:)对于所有键/修饰符组合,此模式都会重复其自身。
苹果文档中的两个领域似乎是相关的:
通过阅读这些文档,系统似乎负责将关键事件映射到相应的关键操作。事实上,当没有按下修饰符键时,这对我是有效的。但是当按下修饰符键时,事件就会像其他事件一样被处理,并通过正常的响应链。
(我可以看到修饰符key事件是通过NSApplication sendEvent传入的,尽管NSApplication sendAction:to:from:从未被调用过,并且在视图层次结构中继续进行,考虑到我阅读了上面的文档,我希望这样做。
文档提示文本编辑视图可能受到不同的对待。这些键盘操作是否仅发送到编辑文本的视图?如果不是,那么当用户按下moveUpAndModifySelection:时,如何在自定义NSView类上调用像Shift-Up这样的消息?
作为参考,我将此图表用于键盘绑定,不过坦率地说,我已经尝试了几乎所有组合,列出了还是没有:
到头来,我可能只是覆盖keyDown:并手动处理我感兴趣的所有组合,但我希望至少能够理解为什么这不像我想要的那样工作。
(请注意,此处的目标应用程序是允许用户导航类似网格的项视图,非常类似于集合视图。)
如有任何建议、建议或评论,将不胜感激。
更新:
如果在keyDown中执行以下操作
- (void)keyDown:(NSEvent *)theEvent {
...
[self interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
}然后将在自定义视图上调用“正确”操作。我认为这是因为我感兴趣的操作是类似文本的操作,这要求输入管理器解释并转换为它们的适当操作。
我仍然不完全清楚为什么要正确地调用moveUp:。响应链中的谁正在识别被按下的Up箭头键,然后发送moveUp:消息?
发布于 2014-03-29 03:59:48
这是对你的自我回答的某种回答,这更多的是问题的延伸。
是的,在大多数情况下,需要调用-[NSResponder interpretKeyEvents:]或-[NSTextInputContext handleEvent:]来获得键绑定系统,以向您发送绑定操作方法。
至于为什么要获得-moveUp:,我在一个简单的自定义视图类中实现了以下内容:
- (BOOL) acceptsFirstResponder
{
return YES;
}
- (void) moveUp:(id)sender
{
NSLog(@"%@", [NSThread callStackSymbols]);
}它记录了以下调用堆栈:
0 TestKeyUp 0x000000010000182d -[KeyView moveUp:] + 48
1 AppKit 0x00007fff85e44012 -[NSWindow _processKeyboardUIKey:] + 325
2 AppKit 0x00007fff85ab1075 -[NSWindow keyDown:] + 94
3 AppKit 0x00007fff8589e206 forwardMethod + 104
4 AppKit 0x00007fff8589e206 forwardMethod + 104
5 AppKit 0x00007fff8596c0c7 -[NSWindow sendEvent:] + 8769
6 AppKit 0x00007fff858a0afa -[NSApplication sendEvent:] + 4719
7 AppKit 0x00007fff858376de -[NSApplication run] + 474
8 AppKit 0x00007fff858303b0 NSApplicationMain + 364
9 TestKeyUp 0x000000010000176d main + 33
10 TestKeyUp 0x0000000100001744 start + 52
11 ??? 0x0000000000000001 0x0 + 1NSWindow将向上箭头键作为“键盘接口控制”的一部分处理。这是部分记录,但不清楚它将调用诸如-moveUp:之类的方法。显然,这就是它的实现方式。
发布于 2014-03-29 00:53:05
通过阅读这些文档,系统似乎负责将关键事件映射到相应的关键操作。
没有“制度”。NSResponder的工作方式如下:将任意消息(只是字符串)拖放到响应链的开头(任何有键盘焦点的东西)。通常它什么也不做,然后把它传递给“下一个”响应者。它沿着响应链,什么也不做,直到50或60零操作后,终于有人说:“是的,我会对此作出反应!”它起到了一定的作用。一旦发生这种情况,响应者链上的任何东西都不会知道事件发生了。
通常,一个应答者会触发另一个应答者。例如,如果您为keyDown:发送一条Cmd-S消息,它将不会一直执行任何操作,直到它最终到达"save“菜单项,然后将saveDocument:放在响应链的开头,然后再一次将整个事件向下运行,直到到达NSDocument,后者将执行保存操作。
令人困惑的是,每当使用修饰符键按下
moveUp:箭头键时,都会调用Up。当持有修饰符键(e.x.:Ctl-Up)时,我希望调用适当的键盘操作方法。 例如:
Ctl-Up -> moveUp: (预期:scrollPageUp:)Alt-Up -> moveUp: (预期:moveToBeginningOfParagraph:)Shift-Up -> moveUp: (预期:moveUpAndModifySelection:)Command-Up -> moveUp: (预期:moveToBeginningOfDocument:)这并不令人困惑,响应链不知道任何关于滚动视图或文本视图或任何东西的信息。它只知道应用程序将一条keyDown或mouseDown:消息推到了链上,一毫秒后,一条scrollPageUp:消息被推到了链上,或者可能没有。在响应链中有很多东西从来没有被使用过。如果您需要它们,它们可以被触发,而且有些东西将由AppKit触发,但很多事情不是。
请注意,NSResponder中的方法列表主要是为了让代码自动完成的开发人员更容易使用,并在用GUI构建界面时填充可用操作的列表。您可以将任何@selector()放在响应链上(只要它有一个sender参数)。并不是所有正在使用的都被记录在案。
到头来,我可能只是重写keyDown:手动处理我感兴趣的所有组合,但我希望至少能够理解为什么这不像我想要的那样工作。
是啊。如果可能的话,您应该让keyDown:做一些类似于[self moveUpAndModifySelection:self];的事情。所以基本上是一个大开关语句或者if语句,没有太多的逻辑。
不管怎样,我就是这么做的:https://github.com/abhibeckert/Dux/blob/master/Dux/DuxTextView.m#L797
https://stackoverflow.com/questions/22725329
复制相似问题