Keymap,InputMap,ActionMap,KeyListener - 选择重载

时间:2016-04-15 12:43:10

标签: java swing keylistener key-bindings jcomponent

我无法找到关于所有这些之间关系的简明回答,以便我可以选择最佳实践并继续前进。 JTextComponent有:

  • addKeyListener(..)。我们使用可在KeyListenerkeyPressed(..)等事件中调用的方法编写keyTyped(..),我们可以查询这些事件:event.getKeyCode()

  • addKeymap(..)setKeymap(..)KeymapaddActionForKeyStroke(..),其中KeyStroke(我们可以通过调用KeyStroke指定字符或键代码的静态方法获取),以及ActionActionListener,有铃声和口哨声。

  • getInputMap(..)getActionMap(..)InputMapKeyStroke(如上所示)映射到StringActionMap将字符串映射到Action(如上所示)。 Java教程How to use key bindings谈到了这一点。

这是获得相同功能的三种冗余方式。除了比较优势/劣势之外,这还提出了这三种机制如何共存的自然问题?哪些优先于其他人?

1 个答案:

答案 0 :(得分:4)

  • InputMap + ActionMap系统在1.3中引入,并替换了较早的Keymap(使用InputMap + ActionMap系统重新实现了引擎盖,用于向后兼容)。新系统具有Keymap功能的超集。 (摘自Loy和Eckstein撰写的O' Reilly书籍 Java Swing page 755。)

  • 因此,我们不必担心Keymap新代码。

  • How to use key bindings中的Java教程甚至没有提及Keymap,但它确实解决了KeyListener s vs key 绑定(即InputMap + ActionMap设施):

    • 由于焦点和组件包含层次结构(它不知道)的问题,KeyListener方法需要更多的工作。例如,如果我们有一个表组件和一个包含焦点的table-cell组件,按键会将事件发送到表格单元组件,它将取决于我们将它们转发到表中(因为我们想要更改表格当前选择的单元格)。

    • 相反,键绑定让我们直接在父组件上指定绑定:每个JComponent三个 InputMap s和一个ActionMap 。输入地图属于以下类型:JComponent.WHEN_FOCUSEDWHEN_ANCESTOR_OF_FOCUSED_COMPONENTWHEN_IN_FOCUSED_WINDOW。与侦听器不同,其中聚焦组件上的所有KeyListener按顺序处理,通过键绑定,事件将在层次结构中向上传播(嗯,我认为是树,如每个组件只有一个父项),直到找到一个动作(没有被禁用),即停止时。在此搜索过程中,第二种InputMap优先于第三种类型。

    • KeyListener优先于密钥绑定机制。在处理组件的KeyListener时,其中一个可能e.consume(),然后事件不再达到KeyListener,也不会达到键绑定层次结构。首先处理最后添加的键侦听器。

  • 因此,虽然键绑定方法从头开始设置会更麻烦(您必须给Action一个名称,并调用两个方法将它绑定到{{1} {}通过InputMapAbstractAction通过ActionMap),它似乎应该是响应按键分配要调用的函数的第一个调用点。 KeyStroke使您可以执行更多操作(例如,异乎寻常的密钥组合 - 超出KeyListener可以处理的范围;并允许更早访问密钥事件,并且能够KeyStroke,但关键绑定更方便,可以预测基本用例。

相关点(由related question建议)是另一种处理文本组件的冗余机制,尤其是:DocumentListenersDocumentFilters。当重新映射键的原因是控制文本组件中文本发生的变化时,这些更加方便且易于发现。

另请参阅:关于密钥绑定系统从引入时起如何工作的详细信息的报告archived version