我已经在key bindings上阅读了几次明确的教程,但是我的脑缓存似乎不足以容纳复杂的过程。
我正在调试一个键绑定问题(事实证明我使用了错误的JComponent.WHEN_*
条件),我偶然发现了一个简单而有趣的javadoc for package private javax.swing.KeyboardManager
(不幸的是)匿名Java工程师。
我的问题是这样的:除了KeyEventDispatcher
在开头检查时,描述是否遗漏和/或错误?
KeyboardManager类用于 帮助调度键盘操作 WHEN_IN_FOCUSED_WINDOW样式操作。 其他条件的行动是 直接在JComponent中处理。
这是对语义的描述 [原文如此]如何键盘调度 应该像我一样至少工作[原文如此] 明白它。
KeyEvents被分派到 重点部分。焦点经理 在处理此问题时获得第一次破解 事件。如果焦点管理员没有 想要它,然后JComponent调用 super.processKeyEvent()允许 听众有机会处理 事件。
如果没有听众“消费” 事件然后键绑定得到一个 射击。这是事情的起点 变得有趣。首先,KeyStokes [sic]用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。)
答案 0 :(得分:1)
我们需要从Component.dispatchEventImpl开始调试。
只需阅读该方法的源注释,就可以了解事件如何在Swing中流动(您也可以从EventQueue.pumpEventsForHeirarchy开始向上一级)。
为清楚起见,让我从代码中摘录一下:
现在,您可以将上述流程与您的说明进行匹配,以确定其是否正确。但重点是你应该真的不依赖于私有类的javadoc,原因是开发人员通常不关心在代码更改时更新私有类的注释,因此文档可能会过时。