如何使用键绑定
JComponent
类支持键绑定,作为对用户键入的各个键做出响应的一种方式。以下是一些适当的键绑定示例:
-
您正在创建一个自定义组件,并希望支持对其的键盘访问。
例如,您可能希望组件在获得焦点并且用户按下 Space 键时做出反应。 -
您要覆盖现有键绑定的行为。
例如,如果您的应用程序通常以特定的方式对 F2 键的按下作出反应,则您可能希望它执行其他操作或忽略按键。 -
您想为现有操作提供新的键绑定。
例如,您可能强烈感到 Control-Shift-Insert 应该执行粘贴操作。
您通常不需要直接使用键绑定。助记符(由所有按钮,选项卡式窗格以及JLabel支持)和加速器(由菜单项支持)在后台使用它们。您可以在启用键盘操作部分中找到助记符和加速器的内容。
键绑定的替代方法是使用key listeners。按键侦听器是键盘 Importing 的低级interface,但是对于响应单个按键,按键绑定更为合适,并且往往会导致代码维护更加容易。如果要在组件没有焦点时激活键绑定,则键侦听器也很困难。按键绑定的一些优点是它们可以自我记录,考虑容纳层次结构,鼓励可重用的代码块(Action
对象)以及允许轻松删除,自定义或共享操作。而且,它们使更改动作绑定的键变得容易。动作的另一个优点是它们具有启用状态,该状态提供了一种简便的方法来禁用该动作而不必跟踪其附加到哪个组件。
本节的其余部分为您提供了使用键绑定所需的详细信息:
按键绑定的工作方式
JComponent
提供的键绑定支持取决于InputMap和ActionMap类。ImportingMap 将击键绑定到动作名称,并且动作 Map 指定与每个动作名称相对应的action。从技术上讲,您无需在 Map 中使用动作名称;您可以将任何对象用作 Map 的“键”。但是,按照约定,您使用一个字符串 来命名一个动作。
每个InputMap
/ActionMap
都有一个通常来自用户interface的父级。每当外观改变时,都会重置父级。这样,开发人员指定的任何绑定都不会在外观更改时丢失。
每个JComponent
都有一个动作图和三个 Importing 图。ImportingMap 对应于以下焦点情况:
-
JComponent.WHEN_FOCUSED
- 该组件具有键盘焦点。
WHEN_FOCUSED
ImportingMap 通常在组件没有子代时使用。例如,按钮使用WHEN_FOCUSED
Map 绑定 Space 键。
这些绑定仅在组件具有焦点时才有效。
- 该组件具有键盘焦点。
-
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
- 该组件包含(或是)具有焦点的组件。此 ImportingMap 通常用于复合组件,即其实现取决于子组件的组件。例如,
JTable
使用WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
进行所有绑定,因此,如果用户正在编辑,则向上箭头键(例如)仍会更改所选单元格。
- 该组件包含(或是)具有焦点的组件。此 ImportingMap 通常用于复合组件,即其实现取决于子组件的组件。例如,
-
JComponent.WHEN_IN_FOCUSED_WINDOW
- 组件的窗口要么具有焦点,要么包含具有焦点的组件。此 ImportingMap 通常用于助记符或加速器,无论焦点在窗口中的什么位置,它们都必须处于活动状态。
当用户键入一个键时,JComponent
键事件处理代码将搜索一个或多个 ImportingMap,以找到该键的有效绑定。找到绑定后,它将在操作 Map 中查找相应的操作。如果启用了操作,则绑定有效并且执行该操作。如果已禁用,则 continue 搜索有效的绑定。
如果该键存在多个绑定,则仅使用找到的第一个有效绑定。ImportingMap 按以下 Sequences 检查:
-
重点组件的
WHEN_FOCUSED
Importing 图。 -
重点组件的
WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
Importing 图。 -
WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
ImportingMap 的是焦点组件的父级,然后是其父级的父级,依此类推,从而 continue 包含层次结构。注意:将跳过禁用组件的 ImportingMap。 -
搜索聚焦窗口中所有已启用组件的
WHEN_IN_FOCUSED_WINDOW
ImportingMap。由于搜索组件的 Sequences 是不可预测的,因此请 避免重复WHEN_IN_FOCUSED_WINDOW
绑定!
让我们考虑一下在两种典型的键绑定情况下发生的情况:一个按钮对 Space 键作出反应,一个带有默认按钮的框架对 Enter 键作出反应。
在第一种情况下,假定用户在JButton
拥有键盘焦点的同时按下了 Space 键。首先,将事件通知给按钮的键侦听器。假设所有按键侦听器都不消耗该事件(通过在KeyEvent
上调用consume方法),则查询按钮的WHEN_FOCUSED
ImportingMap。找到绑定是因为JButton
使用该 ImportingMap 将 Space 绑定到动作名称。在按钮的动作 Map 中查找动作名称,并调用该动作的actionPerformed
方法。 KeyEvent
已消耗,并且处理停止。
在第二种情况下,假定焦点位于具有默认按钮(使用JRootPane
setDefaultButton方法设置)的框架内的任何位置时,按下 Enter 键。无论关注的组件是什么,都将首先通知其关键侦听器。假设它们都不消耗键事件,则将查询焦点组件的WHEN_FOCUSED
ImportingMap。如果没有针对该键的绑定,或者禁用了与该键绑定的操作,那么将查询该焦点组件的WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
ImportingMap,然后(如果未找到绑定或禁用与该键绑定的 Action),则针对每个组件的WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
ImportingMap 包含层次结构中组件祖先的数量。final,搜索根窗格的WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
ImportingMap。由于该 ImportingMap 具有 Enter 的有效绑定,因此将执行该操作,从而导致单击默认按钮。
如何制作和删除按键绑定
这是指定组件应对 F2 键做出反应的示例:
component.getInputMap().put(KeyStroke.getKeyStroke("F2"),
"doSomething");
component.getActionMap().put("doSomething",
anAction);
//where anAction is a javax.swing.Action
如前面的代码所示,要获取组件的操作图,请使用getActionMap
方法(从JComponent
继承)。要获取 ImportingMap,可以使用getInputMap(int)
方法,其中整数是前面列表中所示的JComponent.WHEN_*FOCUSED*
常量之一。或者,在通常情况下常量为JComponent.WHEN_FOCUSED
的情况下,可以只使用不带参数的getInputMap
。
要将条目添加到其中一个 Map,请使用put
方法。您可以使用KeyStroke
对象指定键,您可以使用KeyStroke.getKeyStroke(String)方法获得该键。您可以在如何使用动作中找到创建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);
//where pressedAction and releasedAction are javax.swing.Action objects
要使组件忽略其通常响应的键,可以使用特殊操作名称“ none”。例如,以下代码使组件忽略 F2 键。
component.getInputMap().put(KeyStroke.getKeyStroke("F2"),
"none");
Note:
前面的代码不会阻止在相关的WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
和WHEN_IN_FOCUSED_WINDOW
ImportingMap 中搜索 F2 键绑定。为防止此搜索,您必须使用有效的操作而不是“ none”。例如:
Action doNothing = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
//do nothing
}
};
component.getInputMap().put(KeyStroke.getKeyStroke("F2"),
"doNothing");
component.getActionMap().put("doNothing",
doNothing);
密钥绑定 API
下表列出了常用的键绑定 API。另请参阅如何使用动作部分中的 API 表创建和使用动作。
Method | Purpose |
---|---|
InputMap getInputMap() | |
InputMap getInputMap(int) (在 JComponent 中) | 获取组件的 ImportingMap 之一。参数可以是以下JComponent 常量之一:WHEN_FOCUSED ,WHEN_IN_FOCUSED_WINDOW 或WHEN_ANCESTOR_OF_FOCUSED_COMPONENT 。无参数方法获取WHEN_FOCUSED ImportingMap。 |
无效 put(KeyStroke,Object) (在 InputMap 中) | 设置与指定按键相关联的动作名称。如果第二个参数是null ,则此方法将删除按键的绑定。要忽略按键,请使用"none" 作为第二个参数。 |
静态 KeyStroke getKeyStroke(String) (在 KeyStroke 中) | 获取指定特定用户键盘活动的对象。典型的参数是“ alt shift X”,“ INSERT”和“ typed a”。有关详细信息和getKeyStroke 方法的其他形式,请参见KeyStroke API 文档。 |
Method | Purpose |
---|---|
ActionMap getActionMap() | |
(在 JComponent 中) | 获取将名称 Map 为组件操作的对象。 |
无效 put(Object,Action) (在 ActionMap 中) | 设置与指定名称关联的操作。如果第二个参数是null ,则此方法将删除名称的绑定。 |
使用键绑定的示例
下表列出了使用键绑定的示例:
Example | Where Described | Notes |
---|---|---|
TableFTFEditDemo | 如何使用表格 | IntegerEditor类在格式文本字段上注册键绑定,以在用户按下 Enter 键时验证 Importing。 |
TextComponentDemo | Literals 组件功能 | 当用户按下 Control-B,Control-F,Control-P 和 Control-N 键时,键绑定将注册在文本窗格上,以浏览文本。 |