Java如何调度KeyEvent? [英] How does Java dispatch KeyEvents?

查看:296
本文介绍了Java如何调度KeyEvent?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已阅读有关键绑定的明确教程几次,但是我的大脑缓存似乎不足以容纳复杂的过程.

I've read the definite tutorial on key bindings a few times, but my brain cache doesn't seem large enough to hold the complicated processes.

我正在调试一个键绑定问题(结果是我使用了错误的JComponent.WHEN_*条件),然后我偶然发现了一个简单而搞笑的Javadoc,用于私有包

I was debugging a key binding problem (turned out I was using the wrong JComponent.WHEN_* condition), and I stumbled upon a concise and hilarious javadoc for the package private javax.swing.KeyboardManager by an (unfortunately) anonymous Java engineer.

我的问题是:除了KeyEventDispatcher在一开始就被检查过,描述中是否遗漏和/或有误?

My question is this: except for KeyEventDispatcher which is checked at the very beginning, does the description miss and/or mistake anything?

KeyboardManager类用于 帮助调度键盘操作 WHEN_IN_FOCUSED_WINDOW样式的动作. 具有其他条件的动作是 直接在JComponent中处理.

The KeyboardManager class is used to help dispatch keyboard actions for the WHEN_IN_FOCUSED_WINDOW style actions. Actions with other conditions are handled directly in JComponent.

这里是对共鸣的描述 [sic]键盘调度的方式 应该至少像我一样 明白它.

Here's a description of the symantics [sic] of how keyboard dispatching should work atleast [sic] as I understand it.

KeyEvent被调度到 重点组件.焦点经理 在处理此问题时首先遇到麻烦 事件.如果焦点经理没有 想要它,然后JComponent调用 super.processKeyEvent()这允许 听众有机会处理 事件.

KeyEvents are dispatched to the focused component. The focus manager gets first crack at processing this event. If the focus manager doesn't want it, then the JComponent calls super.processKeyEvent() this allows listeners a chance to process the event.

如果没有一个听众消费" 事件,然后按键绑定得到一个 射击.这是事情开始的地方 变得有趣.首先,按键 [原文]用WHEN_FOCUSED定义 条件有机会.如果没有 这些想要事件,然后 组件走,虽然是[原文]父母 寻找类型的动作 WHEN_ANCESTOR_OF_FOCUSED_COMPONENT.

If none of the listeners "consumes" the event then the keybindings get a shot. This is where things start to get interesting. First, KeyStokes [sic] defined with the WHEN_FOCUSED condition get a chance. If none of these want the event, then the component walks though it's [sic] parents looked for actions of type WHEN_ANCESTOR_OF_FOCUSED_COMPONENT.

如果还没有人接受它,那么它 在这里结束.然后我们寻找 已注册的组件 WHEN_IN_FOCUSED_WINDOW事件和火灾 给他们.请注意,如果这些都不是 被找到,然后我们将事件传递给 菜单栏,让他们有一个裂缝 在它.它们的处理方式不同.

If no one has taken it yet, then it winds up here. We then look for components registered for WHEN_IN_FOCUSED_WINDOW events and fire to them. Note that if none of those are found then we pass the event to the menubars and let them have a crack at it. They're handled differently.

最后,我们检查是否正在查看 一个内部框架.如果我们是,否 一个人想要活动,然后我们往前走 给InternalFrame的创建者看 如果有人想要该事件(依此类推) 等等.

Lastly, we check if we're looking at an internal frame. If we are and no one wanted the event then we move up to the InternalFrame's creator and see if anyone wants the event (and so on and so on).


(更新)如果您曾经对键绑定指南中的粗体警告有所疑问:


(UPDATE) If you've ever wondered about this bold warning in the key bindings guide:

因为搜索组件的顺序是不可预测的,所以避免重复的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;
         }
     }

因此搜索顺序实际上是可预测的,但显然取决于此特定实现,因此最好完全不依赖它.使其无法预测.

So the order of searching is actually predictable, but obviously dependent on this particular implementation, so it's better not to rely on it at all. Keep it unpredictable.

(Javadoc和代码来自WinXP上的jdk1.6.0_b105.)

(Javadoc and code is from jdk1.6.0_b105 on WinXP.)

推荐答案

我们需要从

We need to start debugging from Component.dispatchEventImpl.
Just reading through the source comments of the method should give you the perfect idea of how events flow in Swing(you can also start one level up from EventQueue.pumpEventsForHeirarchy).

为清楚起见,让我从代码中摘录:

For clarity just let me give an extract from the code:

  1. 设置时间戳记和当前事件的修饰符.预调度员.在通知AWTEventListener之前,请在此处进行任何必要的重新定位/重新排序.
  2. 允许工具包将此事件传递给AWTEventListeners.
  3. 如果没有人消耗键事件,请让KeyboardFocusManager处理它.
  4. 允许使用输入法来处理事件
  5. 在交付之前对特殊事件进行预处理
  6. 传递事件以进行正常处理
  7. 4061116的特殊处理:钩住浏览器以关闭模式对话框.:)
  8. 允许对等方处理事件.除KeyEvent外,它们将在所有KeyEventPostProcessor之后被对等方处理(请参见DefaultKeyboardFocusManager.dispatchKeyEvent())

现在,您可以将上述流程与您的描述进行匹配,以确定其是否正确.但是关键是您真的不应该依赖私有类的javadocs,原因是开发人员通常不关心代码更改时更新私有类的注释,因此文档可能会过时.

Now you can match the above flow with your description to determine whether its right or not. But the point is you should really not depend on javadocs of private classes, the reason being that the developers usually dont care to update the comments of private classes when code changes, so the docs may become obsolete.

这篇关于Java如何调度KeyEvent?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆