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

Evg*_*eev 2 java swing jcomponent keylistener key-bindings

我找不到关于所有这些之间关系的简明答案,以便我可以选择最佳实践并开始。JTextComponent已:

  • 旧的addKeyListener(..)。我们写一个KeyListener与被调用的方法keyPressed(..)keyTyped(..)等事件,我们可以查询:event.getKeyCode()

  • addKeymap(..)setKeymap(..)。A Keymaphas addActionForKeyStroke(..),它接受 a KeyStroke(我们可以通过调用KeyStroke的静态方法来指定字符或键码)和 an Action,它是一个ActionListener带有花里胡哨的东西。

  • getInputMap(..)getActionMap(..)。AnInputMap将 a KeyStroke(如上)映射到 a String,并将ActionMap字符串映射到 an Action(如上)。Java 教程如何使用键绑定讨论了这一点。

这是实现相同功能的三种冗余方式。除了比较优势/劣势之外,这自然会引发一个问题,即这三种机制如何共存?哪些优先于其他?

Evg*_*eev 6

  • InputMap+ActionMap系统在 1.3 中引入并取代了旧的Keymap(为了向后兼容,在引擎盖下使用InputMap+ActionMap系统重新实现)。新系统具有Keymap. (来自Loy 和 Eckstein的 O'Reilly 书籍Java Swing第 755 页。)

  • 因此,我们无需担心Keymap新代码。

  • 如何使用键绑定中的 Java 教程甚至没有提到Keymap,但它确实解决了KeyListeners 与键绑定(即InputMap+ActionMap设施)的问题:

    • KeyListener的做法需要更多的是因为焦点和组件容器层次结构(它是不知道的)的问题的工作。例如,如果我们有一个 table 组件和一个包含在其中的 table-cell 组件,它具有焦点,按下?键会将事件发送到 table cell 组件,并且由我们将它们中继到 table(因为我们要更改表格当前选定的单元格)。

    • 相比之下,键绑定让我们直接在父组件上指定绑定:每个JComponent都有三个 InputMaps 和一个ActionMap。输入映射有以下类型:JComponent.WHEN_FOCUSEDWHEN_ANCESTOR_OF_FOCUSED_COMPONENTWHEN_IN_FOCUSED_WINDOW。与侦听器不同,在这种KeyListener情况下,焦点组件上的所有s按顺序处理,使用键绑定,事件将沿层次结构向上传播(我认为是一棵树,因为每个组件只有一个父级),直到找到一个动作(尚未禁用),即停止时。InputMap在此搜索过程中,第二种类型优先于第三种类型。

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

  • 因此,虽然从头开始设置键绑定方法需要更多麻烦(您必须给出Action一个名称,并调用两个方法将其绑定到 a KeyStrokevia anInputMap和一个AbstractActionvia the ActionMap),但似乎应该是第一个调用点,用于分配响应按键时调用的函数。KeyListeners 使您能够做更多事情(例如奇异的组合键——超出了KeyStroke处理能力;并允许更早地访问键事件,并有能力访问e.consume()它),但键绑定更方便,可以像它们一样预测基本用例。

相关点(由相关问题建议)是另一种处理文本组件的冗余机制,尤其是:DocumentListenersDocumentFilters。当重新映射键的原因是为了控制文本组件中的文本会发生什么时,这些更加方便和防错。

另请参阅:有关键绑定系统从引入时起如何工作的详细信息的报告,存档版本