Java教程已针对JDK 8编写。本页面中描述的示例和实践不利用后续版本引入的改进,并可能使用不再可用的技术。
请参阅Java语言变化,了解Java SE 9及后续版本中的更新语言功能的摘要。
请参阅JDK发行说明,了解所有JDK版本的新功能、增强功能以及已删除或已弃用选项的信息。
JComponent
类支持按键绑定作为响应用户按键的一种方式。以下是一些适用于按键绑定的示例:
您通常不需要直接使用按键绑定。它们在幕后由助记符(由所有按钮、选项卡窗格以及JLabel
支持)和加速器(由菜单项支持)使用。您可以在启用键盘操作一节中找到助记符和加速器的相关内容。
按键绑定的替代方法是使用键盘监听器。键盘监听器作为与键盘输入的低级接口有其作用,但对于响应单个按键,按键绑定更合适且通常会导致更易于维护的代码。如果要在组件没有焦点时激活按键绑定,键盘监听器也会很困难。按键绑定的一些优点是它们在某种程度上是自文档的,考虑了包含层次结构,鼓励重用代码块(Action
对象),并允许轻松删除、自定义或共享操作。此外,它们使得更改操作绑定的按键变得容易。Actions的另一个优点是它们具有一个启用状态,这提供了一种轻松禁用操作的方式,而无需跟踪它附加到的组件。
本节的其余部分将为您提供使用按键绑定所需的详细信息:
JComponent
提供的按键绑定支持依赖于InputMap
和ActionMap
类。输入映射将按键绑定到操作名称,而操作映射指定与每个操作名称对应的操作。从技术上讲,您不需要在映射中使用操作名称;您可以使用任何对象作为映射的“键”。但按照惯例,您使用命名操作的字符串作为“键”。
每个InputMap
/ActionMap
都有一个通常来自UI的父级。每次更改外观和感觉时,父级都会重置。通过这种方式,开发人员指定的绑定在外观和感觉变化时永远不会丢失。
每个JComponent
有一个动作映射和三个输入映射。输入映射对应于以下焦点情况:
JComponent.WHEN_FOCUSED
WHEN_FOCUSED
输入映射。例如,按钮使用WHEN_FOCUSED
映射将空格键绑定在按钮上。
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
JTable
使用WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
创建所有绑定,这样如果用户正在编辑,向上箭头键(例如)仍然会更改选定的单元格。
JComponent.WHEN_IN_FOCUSED_WINDOW
当用户键入键时,JComponent
的键事件处理代码会搜索一个或多个输入映射以找到有效的绑定。当找到绑定时,它会在动作映射中查找相应的动作。如果动作已启用,则绑定有效,并执行动作。如果动作已禁用,则继续搜索有效的绑定。
如果键存在多个绑定,则只使用找到的第一个有效绑定。按照以下顺序检查输入映射:
WHEN_FOCUSED
输入映射。WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
输入映射。WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
输入映射,然后是父级的父级,以此类推,一直向上继续容器层次结构。注意:跳过禁用组件的输入映射。WHEN_IN_FOCUSED_WINDOW
输入映射中搜索。由于搜索组件的顺序是不可预测的,避免重复的WHEN_IN_FOCUSED_WINDOW
绑定!让我们考虑两种典型的按键绑定情况:按钮对Space键的反应以及具有默认按钮的框架对Enter键的反应。
在第一种情况下,假设用户在一个JButton
具有键盘焦点时按下了Space键。首先,按钮的键监听器会收到事件的通知。假设没有任何键监听器通过调用KeyEvent
上的consume
方法"消耗"了事件,按钮的WHEN_FOCUSED
输入映射将被咨询。找到一个绑定,因为JButton
使用该输入映射将Space绑定到一个动作名称。在按钮的动作映射中查找该动作名称,并调用该动作的actionPerformed
方法。KeyEvent
被消耗,处理停止。
在第二种情况下,假设在具有默认按钮的框架内的任何位置按下Enter键(使用JRootPane
的setDefaultButton
方法设置默认按钮)。无论焦点在哪个组件上,首先通知其键盘监听器。假设没有任何监听器消耗键盘事件,则会查找焦点组件的WHEN_FOCUSED
输入映射。如果该映射没有绑定键或者绑定到该键的操作被禁用,则会查找焦点组件的WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
输入映射,然后(如果没有找到绑定或者绑定到该键的操作被禁用)查找容器层次结构中每个组件的祖先的WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
输入映射。最终,将搜索根窗格的WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
输入映射。由于该输入映射对Enter键有有效绑定,因此会执行相应的操作,导致默认按钮被点击。
下面是一个示例,指定一个组件应该响应F2键:
component.getInputMap().put(KeyStroke.getKeyStroke("F2"), "doSomething"); component.getActionMap().put("doSomething", anAction); //其中anAction是javax.swing.Action对象
如上述代码所示,要获取组件的动作映射,使用继承自JComponent
的getActionMap
方法。要获取输入映射,可以使用getInputMap(int)
方法,其中整数是上述列表中的JComponent.WHEN_*FOCUSED*
常量之一。或者,在常规情况下,常量为JComponent.WHEN_FOCUSED
,可以直接使用没有参数的getInputMap
方法。
要向其中一个映射添加条目,使用put
方法。可以使用KeyStroke.getKeyStroke(String)
方法来指定键,该方法返回一个KeyStroke
对象。可以在此处找到创建Action
(用于放入动作映射)的示例。
以下是一个稍微复杂一点的示例,指定一个组件应该像用户点击鼠标一样响应Space键。
component.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "pressed"); component.getInputMap().put(KeyStroke.getKeyStroke("released SPACE"), "released"); component.getActionMap().put("pressed", pressedAction); component.getActionMap().put("released", releasedAction); //其中pressedAction和releasedAction是javax.swing.Action对象
要使组件忽略通常会响应的按键,可以使用特殊的动作名称“none”。例如,以下代码使组件忽略 F2 键。
component.getInputMap().put(KeyStroke.getKeyStroke("F2"), "none");
上述代码并不会阻止相关的 WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
和 WHEN_IN_FOCUSED_WINDOW
输入映射被搜索 F2 键绑定。要阻止此搜索,必须使用有效的动作代替“none”。例如:
Action doNothing = new AbstractAction() { public void actionPerformed(ActionEvent e) { //什么都不做 } }; component.getInputMap().put(KeyStroke.getKeyStroke("F2"), "doNothing"); component.getActionMap().put("doNothing", doNothing);
下表列出了常用的键绑定 API。还请参阅 API 表格 创建和使用操作,在章节 如何使用操作 中。
方法 | 目的 |
---|---|
InputMap getInputMap() InputMap getInputMap(int) (在 JComponent 中) |
获取组件的其中一个输入映射。参数可以是以下这些 JComponent 常量之一: WHEN_FOCUSED 、WHEN_IN_FOCUSED_WINDOW 或 WHEN_ANCESTOR_OF_FOCUSED_COMPONENT 。无参数的方法获取 WHEN_FOCUSED 输入映射。 |
void put(KeyStroke, Object) (在 InputMap 中) |
设置与指定的按键绑定关联的动作名称。如果第二个参数是 null ,则此方法将删除按键绑定。要使按键被忽略,可以使用 "none" 作为第二个参数。 |
static KeyStroke getKeyStroke(String) (在 KeyStroke 中) |
获取指定用户键盘活动的对象。常见的参数有 "alt shift X"、"INSERT" 和 "typed a"。有关完整详情和其他形式的 getKeyStroke 方法,请参阅 KeyStroke API 文档。 |
方法 | 目的 |
---|---|
ActionMap getActionMap() (在 JComponent 中) |
获取将名称映射到组件的动作的对象。 |
void put(Object, Action) (在 ActionMap 中) |
设置与指定名称相关联的动作。如果第二个参数为 null ,则此方法将删除该名称的绑定。 |
以下表格列出了使用键绑定的示例:
示例 | 描述位置 | 注释 |
---|---|---|
TableFTFEditDemo | 如何使用表格 | 在格式化文本字段上注册了一个键绑定,以在用户按下 Enter 键时验证输入。 |
TextComponentDemo | 文本组件特性 | 在文本面板上注册了键绑定,以在用户按下 Control-B、Control-F、Control-P 和 Control-N 键时导航文本。 |