Java中的按键绑定与按键监听器

11

我注意到在Java/Swing中,处理按键事件至少有两种不同的方式:

每种方式的优缺点是什么?应该在什么情况下使用其中一种而不是另一种?

2个回答

23
什么时候应该使用其中之一而不是另一个?
自从推出后,建议使用键绑定。KeyListener 是与事件进行低级连接的。 key bindings 页面涵盖了很多我会倾向于使用它们而不是 KeyListener 的原因。它列出了许多在 KeyListener 中“不可用”的选项。例如:
- WHEN_FOCUSED - WHEN_ANCESTOR_OF_FOCUSED_COMPONENT - WHEN_IN_FOCUSED_WINDOW
阅读链接文档的越多,我就越不理解为什么需要问这个问题。例如:
使用键绑定的替代方法是使用键监听器。键监听器作为与键盘输入的低级接口有其用处,但对于响应单个键,键绑定更为适当,并且往往会导致更易于维护的代码。如果组件没有焦点,则键绑定活动时键监听器也很困难。一些键绑定的优点是它们在某种程度上自我记录,考虑包含层次结构,鼓励可重用的代码块(Action对象),并允许轻松删除、定制或共享操作。此外,它们使更改操作绑定的键变得容易。 Actions的另一个优点是它们具有启用状态,这提供了一种轻松禁用操作而无需跟踪其附加到哪个组件的简便方式。

文本组件

正如@Robin所指出的那样, 文本组件也有DocumentListenerDocumentFilter,可添加更适合文本文档的功能。请参见Text Component Features以获取有关文档监听器过滤器的更多信息。


2
如果我们想要一个参考答案,我至少会包括一个“不要将它们用于文本组件,而是使用DocumentListenerDocumentFilter”的段落。许多关于KeyListener的SO问题都与文本组件有关。 - Robin
2
+1,只是想进一步阐述“可重用代码块”的注释。Actions的共享方式可能不太明显。例如,Actions还可以用于创建JMenuItems和JButtons。 - camickr

13
  1. 按键绑定(高级抽象)

优点

  • 可设置和共享

  • 专用于简单的快捷键,没有不需要的副作用(大多数事件都非常简单且可设置)

  • 舒适地解决窗口焦点的任何问题(也可以进行设置,在Java中窗口必须在屏幕上获得焦点)

  • Swing内部使用KeyBindings、内置快捷键、操作,在Key Bindings by @camickr中实现更多有趣的快捷键和操作

  • 输出应该是Swing Action(在Swing中是同样高度的抽象)

缺点

  • 无法覆盖所有键盘键位

  • 不能同时覆盖三个或更多键被按下的情况

  • 代码看起来非常复杂(实际上并不是真的,在大多数情况下,代码比KeyListener中的相同代码更短)

  • 为了获取更多详细信息,请参见@camickr的评论(需要Swing计时器进行重复操作)

  • 无法使用一个在API中实现的方法进行consume()

.

按键监听器(低级别监听器)


优点

  • 非常易于使用,直观

  • 对于一个或两个键事件,代码非常简短

  • 不需要任何关于Swing和Java的知识

  • 可以覆盖三个或更多键被按下的情况(例如:非常复杂的快捷键),然后无论哪个键触发任何事件,都没有关系,它们是独立的按键事件

  • 可以通过编程方式使用event.consume()

  • 可以监听Compound JComponents(例如JComboBox、JSpinner等)的非最终化、内部事件

  • 缺点:

    • 无法访问某些容器和JComponents

    • (J)Component必须是焦点所有者并且必须可以获得焦点

    • 不适用于Swing JComponents

    .

    AWTEventListener


    • 将所有键盘和鼠标事件组合在一起,尽可能低级别地监听Java中的事件

    • 基本上,在基于Swing的大多数GUI中甚至是非常复杂的GUI中,没有理由使用此侦听器

    • 我看到这个侦听器在基于AWT的自定义组件中实现,需要来自本机操作系统的peers

    • 但是,有一个出色的AWTEventListener实现 Application Inactivity and Global Event Listeners by @camickr

    .

    注意:键盘事件的排序因平台而异



    +1 很详细。然而,你不需要一个Swing Timer来重复执行动作。KeyPressed事件会被重复触发。通常建议使用Timer来控制重复间隔。相同的逻辑也适用于KeyEvents。 - camickr
    @Don Hatch 嗯,请问“无法访问x,y位置”是什么意思?我的建议是为了更快得到帮助,请根据SSCCE(简短、可运行、可编译)提出自己的问题。据我所知,同时按下3个或更多按键(快捷键)或按键顺序的实际排序存在限制,对于其余情况,最好使用KeyBindings而不是KeyListener,这样更方便、舒适、易管理。 - mKorbel
    @mKorbel,我之前添加了一条评论,但是它是错误的,所以我将其删除了。我把自己搞糊涂了,并认为keyEvents具有getX()、getY()方法,但实际上并没有。没关系! - Don Hatch

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接