【发布时间】:2010-10-14 03:45:53
【问题描述】:
我已经在key bindings 上阅读了几遍明确的教程,但我的大脑缓存似乎不足以容纳复杂的过程。
我正在调试一个键绑定问题(结果发现我使用了错误的JComponent.WHEN_* 条件),我偶然发现了一个简明有趣的 javadoc 包私有 javax.swing.KeyboardManager 由一位(不幸的)匿名 Java 工程师编写。
我的问题是:除了一开始检查的KeyEventDispatcher,描述是否遗漏和/或错误?
KeyboardManager 类用于 帮助调度键盘动作 WHEN_IN_FOCUSED_WINDOW 风格的动作。 具有其他条件的动作是 直接在 JComponent 中处理。
这是对语义的描述 [原文如此] 如何键盘调度 至少应该像我一样工作 明白它。
KeyEvents 被分派到 重点组件。焦点管理器 第一次处理这个 事件。如果焦点管理器没有 想要它,然后 JComponent 调用 super.processKeyEvent() 这允许 听众有机会处理 事件。
如果没有听众“消费” 事件然后键绑定得到一个 射击。这是事情开始的地方 变得有趣。一、KeyStokes [原文如此] 用 WHEN_FOCUSED 定义 条件获得机会。如果没有 这些想要事件,然后 组件虽然是 [原文如此] 父母 寻找类型的动作 WHEN_ANCESTOR_OF_FOCUSED_COMPONENT。
如果还没有人拿走它,那么它 在这里结束。然后我们寻找 注册的组件 WHEN_IN_FOCUSED_WINDOW 事件并触发 给他们。请注意,如果这些都不是 找到然后我们将事件传递给 菜单栏,让他们有一个裂缝 在它。它们的处理方式不同。
最后,我们检查我们是否正在查看 一个内部框架。如果我们是并且没有 一个想要活动然后我们向上移动 给 InternalFrame 的创建者,看看 如果有人想要这个事件(等等 等等)。
(更新)如果您想知道键绑定指南中的这个粗体警告:
由于搜索组件的顺序不可预测,避免重复的 WHEN_IN_FOCUSED_WINDOW 绑定!
是因为KeyboardManager#fireKeyboardAction中的这一段:
Object tmp = keyMap.get(ks);
if (tmp == null) {
// don't do anything
} else if ( tmp instanceof JComponent) {
...
} else if ( tmp instanceof Vector) { //more than one comp registered for this
Vector v = (Vector)tmp;
// There is no well defined order for WHEN_IN_FOCUSED_WINDOW
// bindings, but we give precedence to those bindings just
// added. This is done so that JMenus WHEN_IN_FOCUSED_WINDOW
// bindings are accessed before those of the JRootPane (they
// both have a WHEN_IN_FOCUSED_WINDOW binding for enter).
for (int counter = v.size() - 1; counter >= 0; counter--) {
JComponent c = (JComponent)v.elementAt(counter);
//System.out.println("Trying collision: " + c + " vector = "+ v.size());
if ( c.isShowing() && c.isEnabled() ) { // don't want to give these out
fireBinding(c, ks, e, pressed);
if (e.isConsumed())
return true;
}
}
所以搜索的顺序实际上是可预测的,但显然依赖于这个特定的实现,所以最好不完全依赖它。保持不可预测性。
(Javadoc 和代码来自 WinXP 上的 jdk1.6.0_b105。)
【问题讨论】:
-
这是对 KeyEvent 处理的一个很好的分析......但我不知道它是否真的是一个可以回答的问题。
-
@BoffinbraiN:我希望有几十个挥杆徽章的人说“据我所知这是正确的”:)
-
是的,那肯定会更好!但我认为,对于这么深的东西,它确实是特定于实现的,而且你已经比大多数勤奋的程序员更仔细地审查了这个实现。 ;) 当然,最好不要让你的代码依赖于这个特定的细节。
-
如果你把它分解成一个问题和一个自我回答,这可能会更好。然后,您可以接受您的答案或让人们对其进行投票。
-
+1 表示“大脑缓存”。 ;-)
标签: java swing key-bindings keyevent