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

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

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

  • addKeymap(..)setKeymap(..)KeymapaddActionForKeyStroke(..) ,它接受KeyStroke (我们可以通过调用指定字符或键代码的KeyStroke的静态方法获得)和Action ,它是一个带有铃声和口哨声的ActionListener

  • getInputMap(..)getActionMap(..)InputMapKeyStroke (如上所示)映射到StringActionMap将字符串映射到Action (如上所述)。 Java教程如何使用键绑定来讨论这个问题。

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

  • InputMap + ActionMap系统在1.3中引入并替换了旧的Keymap (为了向后兼容性,它使用了引擎盖下的InputMap + ActionMap系统重新实现)。 新系统具有Keymapfunction的超集。 (摘自Loy和Eckstein撰写的O’Reilly书籍Java Swing , 第755页 。)

  • 因此,我们不需要担心新代码的Keymap

  • 如何使用键绑定的Java教程甚至没有提到Keymap ,但它确实解决了KeyListener与键绑定 (即InputMap + ActionMap工具):

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

    • 相反,键绑定允许我们直接在父组件上指定绑定:每个JComponent都有三个 InputMap和一个ActionMap 。 输入映射具有以下类型: JComponent.WHEN_FOCUSEDWHEN_ANCESTOR_OF_FOCUSED_COMPONENTWHEN_IN_FOCUSED_WINDOW 。 与侦听器不同,其中焦点组件上的所有KeyListener 按顺序处理,通过键绑定,事件将在层次结构中向上传播(嗯,我认为树,因为每个组件只有一个父组件),直到找到一个动作(尚未被禁用),即停止时。 在此搜索期间,第二种类型的InputMap优先于第三种类型。

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

  • 因此,虽然键绑定方法从头开始设置需要更多麻烦(您必须给Action一个名称,并调用两个方法通过InputMap将它绑定到KeyStroke和通过ActionMap将它绑定到AbstractAction ),它似乎它应该是分配一个函数来响应按键的第一个调用点。 KeyListener使您能够做更多事情(例如奇异的键组合 – 超出KeyStroke可以处理的范围;允许更早访问键事件,能够e.consume()它),但键绑定更方便,预测基本用例就像他们一样。

相关问题(由相关问题建议)是处理文本组件的另一种冗余机制,特别是: DocumentListenerDocumentFilter 。 当重新映射键的原因是控制文本组件中的文本发生什么时,这些更加方便和缺陷。

另请参阅:有关密钥绑定系统从引入时归档版本的详细信息的报告。