Java 中文官方教程 2022 版(二十五)(1)https://developer.aliyun.com/article/1486805
如何编写项目监听器
原文:
docs.oracle.com/javase/tutorial/uiswing/events/itemlistener.html
项目事件由实现ItemSelectable
接口的组件触发。通常,ItemSelectable
组件维护一个或多个项目的开/关状态。触发项目事件的 Swing 组件包括按钮,如复选框、复选菜单项、切换按钮等…以及组合框。
这里是从ComponentEventDemo.java
中提取的一些项目事件处理代码:
*//where initialization occurs* checkbox.addItemListener(this); ... public void itemStateChanged(ItemEvent e) { if (e.getStateChange() == ItemEvent.SELECTED) { label.setVisible(true); ... } else { label.setVisible(false); } }
项目监听器 API
项目监听器接口
因为ItemListener
只有一个方法,所以没有相应的适配器类。
方法 | 目的 |
itemStateChanged(ItemEvent) | 在被监听组件状态改变后调用。 |
项目事件类
方法 | 目的 |
Object getItem() | 返回与状态改变的项目相关联的组件特定对象。通常这是一个包含所选项目文本的String 。 |
ItemSelectable getItemSelectable() | 返回触发项目事件的组件。您可以使用这个方法代替getSource 方法。 |
int getStateChange() | 返回项目的新状态。ItemEvent 类定义了两种状态:SELECTED 和DESELECTED 。 |
使用项目监听器的示例
下表列出了一些使用项目监听器的示例。
示例 | 描述位置 | 注释 |
ComponentEventDemo |
本节和如何编写组件监听器 | 监听复选框上的项目事件,确定标签是否可见。 |
CheckBoxDemo |
如何使用复选框 | 四个复选框共享一个项目监听器,该监听器使用getItemSelected 来确定哪个复选框触发了事件。 |
MenuDemo |
如何使用菜单 | 监听复选框菜单项上的项目事件。 |
MenuDemo |
如何使用滚动窗格 | 监听切换按钮上的项目事件。 |
如何编写键盘监听器
原文:
docs.oracle.com/javase/tutorial/uiswing/events/keylistener.html
按键事件指示用户在键盘上输入时。具体来说,当用户按下或释放键盘键时,具有键盘焦点的组件会触发按键事件。有关焦点的详细信息,请参阅如何使用焦点子系统。
注意:
要定义对特定按键的特殊反应,请使用键绑定而不是键盘监听器。有关更多信息,请参阅如何使用键绑定。
有关两种基本按键事件的通知已发送:
- 输入 Unicode 字符
- 在键盘上按下或释放按键
第一种事件称为按键输入事件。第二种是按键按下或按键释放事件。
通常情况下,您只对按键事件做出反应,除非您需要知道用户何时按下与字符不对应的按键。例如,要知道用户何时输入 Unicode 字符——无论是通过按下一个键(如’a’)还是按顺序按下多个键——您需要处理按键输入事件。另一方面,要知道用户何时按下 F1 键,或者用户是否按下数字键盘上的’3’键,您需要处理按键按下事件。
注意:
要触发键盘事件,组件必须具有键盘焦点。
要使组件获得键盘焦点,请按照以下步骤进行:
- 确保组件的
isFocusable
方法返回true
。这种状态允许组件接收焦点。例如,您可以通过在标签上调用setFocusable(true)
方法为JLabel
组件启用键盘焦点。 - 确保组件在适当时请求焦点。对于自定义组件,实现一个鼠标监听器,在组件被点击时调用
requestFocusInWindow
方法。
版本说明:
焦点子系统会消耗焦点遍历键,如 Tab 和 Shift Tab。如果您需要阻止焦点遍历键被消耗,您可以调用
component.setFocusTraversalKeysEnabled(false)
在触发按键事件的组件上。然后,您的程序必须自行处理焦点遍历。或者,您可以使用KeyEventDispatcher
类预先监听所有按键事件。焦点页面详细介绍了焦点子系统。
您可以获取有关特定按键按下事件的详细信息。例如,您可以查询按键按下事件以确定它是否来自动作键。动作键的示例包括复制、粘贴、上翻页、撤销以及箭头和功能键。您还可以查询按键按下或按键释放事件以确定触发事件的按键位置。大多数按键事件都来自标准键盘,但某些按键的事件,例如 Shift,会提供用户是在键盘左侧还是右侧按下 Shift 键的信息。同样,数字 ‘2’ 可以从标准键盘或数字键盘上输入。
对于按键事件,您可以获取按键字符值以及使用的任何修饰符。
注意:
除非涉及按键输入事件,否则不应依赖从 getKeyChar
返回的按键字符值。
以下示例演示了按键事件。它包括一个文本字段,您可以在其中输入内容,然后是一个文本区域,每当文本字段触发按键事件时,它会显示一条消息。窗口底部的按钮允许您清除文本字段和文本区域中的内容。
尝试一下:
- 点击“启动”按钮以使用Java™ Web Start运行 KeyEventDemo(下载 JDK 7 或更高版本)。或者,要自行编译和运行示例,请参考示例索引。
- 通过按下并释放键盘上的 A 键来输入小写字母 ‘a’。
文本字段触发三个事件:按键按下事件、按键输入事件和按键释放事件。请注意,按键输入事件没有按键代码信息,按键按下和按键释放事件没有按键字符信息。到目前为止,所有事件都不是来自修饰键或动作键,而在按键按下和按键释放事件中报告的按键位置很可能是标准的。 - 按下清除按钮。
您可能希望在以下每个步骤之后执行此操作。 - 按下并释放 Shift 键。
文本字段触发两个事件:按键按下和按键释放。文本字段不会触发按键输入事件,因为 Shift 键本身不对应任何字符。 - 通过按下 Shift 和 A 键来输入大写字母 ‘A’。
您将看到以下事件,尽管可能不是按照这个顺序:按键按下(Shift)、按键按下(A)、按键输入(‘A’)、按键释放(A)、按键释放(Shift)。请注意,Shift 在按键输入和按键按下事件中被列为修饰键。 - 通过按下并释放大写锁定键,然后按下 A 键来输入大写字母 ‘A’。
你应该看到以下事件:按下键(大写锁定键),按下键(A),键输入(‘A’),释放键(A)。注意大写锁定键并未列为修饰键。 - 按下 Tab 键。键盘事件监听器不会接收到 Tab 键按下或释放的事件。这是因为焦点子系统会消耗焦点遍历键,比如 Tab 和 Shift Tab。再按两次 Tab 键将焦点返回到文本区域。
- 按下功能键,比如 F3。你会发现功能键是一个动作键。
- 先按下左 Shift 键,然后按下右 Shift 键。按下和释放事件会指示哪个 Shift 键被按下。
- 如果你的键盘有数字键盘,按下数字锁定键。
至于大写锁定键,有一个按下事件,但没有释放事件。 - 在数字键盘上按下 ‘2’ 键。你会看到数字 ‘2’ 的按下、键输入和释放事件。
- 在标准键盘上按下 ‘2’ 键。同样,你会看到三个事件消息。两个数字 2 键的键输入事件是相同的。但按下和释放事件会显示不同的键代码和不同的键位置。
- 再次按下数字锁定键。会触发一个释放事件。
你可以在KeyEventDemo.java
中找到示例代码。这是演示的键盘事件处理代码:
public class KeyEventDemo ... implements KeyListener ... { *...//where initialization occurs:* typingArea = new JTextField(20); typingArea.addKeyListener(this); //Uncomment this if you wish to turn off focus //traversal. The focus subsystem consumes //focus traversal keys, such as Tab and Shift Tab. //If you uncomment the following line of code, this //disables focus traversal and the Tab events //become available to the key event listener. //typingArea.setFocusTraversalKeysEnabled(false); ... /** Handle the key typed event from the text field. */ public void keyTyped(KeyEvent e) { displayInfo(e, "KEY TYPED: "); } /** Handle the key-pressed event from the text field. */ public void keyPressed(KeyEvent e) { displayInfo(e, "KEY PRESSED: "); } /** Handle the key-released event from the text field. */ public void keyReleased(KeyEvent e) { displayInfo(e, "KEY RELEASED: "); } ... private void displayInfo(KeyEvent e, String keyStatus){ //You should only rely on the key char if the event //is a key typed event. int id = e.getID(); String keyString; if (id == KeyEvent.KEY_TYPED) { char c = e.getKeyChar(); keyString = "key character = '" + c + "'"; } else { int keyCode = e.getKeyCode(); keyString = "key code = " + keyCode + " (" + KeyEvent.getKeyText(keyCode) + ")"; } int modifiersEx = e.getModifiersEx(); String modString = "extended modifiers = " + modifiersEx; String tmpString = KeyEvent.getModifiersExText(modifiersEx); if (tmpString.length() > 0) { modString += " (" + tmpString + ")"; } else { modString += " (no extended modifiers)"; } String actionString = "action key? "; if (e.isActionKey()) { actionString += "YES"; } else { actionString += "NO"; } String locationString = "key location: "; int location = e.getKeyLocation(); if (location == KeyEvent.KEY_LOCATION_STANDARD) { locationString += "standard"; } else if (location == KeyEvent.KEY_LOCATION_LEFT) { locationString += "left"; } else if (location == KeyEvent.KEY_LOCATION_RIGHT) { locationString += "right"; } else if (location == KeyEvent.KEY_LOCATION_NUMPAD) { locationString += "numpad"; } else { // (location == KeyEvent.KEY_LOCATION_UNKNOWN) locationString += "unknown"; } *...//Display information about the KeyEvent...* } }
键盘监听器 API
键盘监听器接口
对应的适配器类是KeyAdapter
。
方法 | 目的 |
keyTyped(KeyEvent) | 在用户在监听组件中键入 Unicode 字符后调用。 |
keyPressed(KeyEvent) | 在用户按下监听组件焦点时调用。 |
keyReleased(KeyEvent) | 在用户释放监听组件焦点时调用。 |
KeyEvent 类
KeyEvent
类从InputEvent
类继承了许多有用的方法,比如 getModifiersEx
,以及从ComponentEvent
和 AWTEvent
类继承了一些有用的方法。在鼠标监听器页面的 InputEvent 类表中查看完整列表。
方法 | 目的 |
int getKeyChar() | 获取与此事件关联的 Unicode 字符。仅在按键输入事件中依赖此值。 |
int getKeyCode() | 获取与此事件关联的键码。键码标识用户按下或释放的键盘上的特定键。KeyEvent 类为常见键定义了许多键码常量。例如,VK_A 指定标记为A的键,VK_ESCAPE 指定 Escape 键。 |
String getKeyText(int) String getKeyModifiersText(int) | 分别返回事件的键码和修饰键的文本描述。 |
int getModifiersEx() String getModifiersExText(int modifiers) | 返回此事件的扩展修饰符掩码。有从InputEvent 类继承的方法。扩展修饰符表示所有模态键的状态。getModifiersExText 方法返回描述扩展修饰符键和鼠标按钮的字符串。由于getModifiersEx 和getModifiersExText 方法提供了更多关于按键事件的信息,因此它们比getKeyText 或getKeyModifiersText 方法更受青睐。 |
boolean isActionKey() | 如果触发事件的键是动作键,则返回 true。动作键的示例包括剪切、复制、粘贴、翻页、大写锁定、箭头和功能键。此信息仅适用于按键按下和按键释放事件。 |
int getKeyLocation() | 返回触发此事件的键的位置。这提供了一种区分键盘上出现多次的键的方法,例如两个 Shift 键。可能的值为KEY_LOCATION_STANDARD 、KEY_LOCATION_LEFT 、KEY_LOCATION_RIGHT 、KEY_LOCATION_NUMPAD 或KEY_LOCATION_UNKNOWN 。对于按键输入事件,此方法始终返回KEY_LOCATION_UNKNOWN 。 |
使用键盘监听器的示例
下表列出了使用键盘监听器的示例。
示例 | 描述位置 | 注释 |
KeyEventDemo |
本节 | 报告发生在文本字段上的所有按键事件,以演示触发按键事件的情况。 |
如何编写列表数据监听器
原文:
docs.oracle.com/javase/tutorial/uiswing/events/listdatalistener.html
当可变列表的内容发生变化时,会触发列表数据事件。由于模型而不是组件触发这些事件,因此您必须向列表模型注册列表数据监听器。如果您没有显式创建具有可变列表模型的列表,则您的列表是不可变的,其模型不会触发这些事件。
注意:
组合框 模型也会触发列表数据事件。但是,除非你正在创建自定义组合框模型,否则通常不需要了解它们。
以下示例演示了可变列表上的列表数据事件:
试试这个:
- 点击启动按钮以使用Java™ Web Start运行 ListDataEventDemo(下载 JDK 7 或更高版本)。或者,要自行编译和运行示例,请参考示例索引。
- 输入你最喜欢的滑雪胜地的名称,然后点击添加按钮。将触发一个
intervalAdded
事件。 - 在列表中选择几个连续的项目,然后点击删除按钮。将触发一个
intervalRemoved
事件。 - 选择一个项目,然后使用箭头按钮将其上移或下移。将触发两个
contentsChanged
事件 — 一个是移动的项目,另一个是被替换的项目。
你可以在ListDataEventDemo.java
中找到演示的代码。以下是在列表模型上注册列表数据监听器并实现监听器的代码:
//*...where member variables are declared...* private DefaultListModel listModel; ... //Create and populate the list model listModel = new DefaultListModel(); ... listModel.addListDataListener(new MyListDataListener()); class MyListDataListener implements ListDataListener { public void contentsChanged(ListDataEvent e) { log.append("contentsChanged: " + e.getIndex0() + ", " + e.getIndex1() + newline); } public void intervalAdded(ListDataEvent e) { log.append("intervalAdded: " + e.getIndex0() + ", " + e.getIndex1() + newline); } public void intervalRemoved(ListDataEvent e) { log.append("intervalRemoved: " + e.getIndex0() + ", " + e.getIndex1() + newline); } }
列表数据监听器 API
列表数据监听器接口
ListDataListener
没有对应的适配器类。
方法 | 目的 |
intervalAdded(ListDataEvent) | 当一个或多个项目被添加到列表时调用。 |
intervalRemoved(ListDataEvent) | 当一个或多个项目从列表中被移除时调用。 |
contentsChanged(ListDataEvent) | 当列表中一个或多个项目的内容发生更改时调用。 |
ListDataEvent API
方法 | 目的 |
Object getSource() (在 java.util.EventObject 中) |
返回触发事件的对象。 |
int getIndex0() | 返回值发生更改的第一个项目的索引。 |
int getIndex1() | 返回值发生更改的最后一个项目的索引。 |
int getType() | 返回事件类型。可能的值为:CONTENTS_CHANGED 、INTERVAL_ADDED 或 INTERVAL_REMOVED 。 |
使用列表数据监听器的示例
下表列出了使用列表数据监听器的示例。
示例 | 描述位置 | 备注 |
ListDataEventDemo |
本节 | 报告列表上发生的所有列表数据事件。 |
如何编写列表选择监听器
原文:
docs.oracle.com/javase/tutorial/uiswing/events/listselectionlistener.html
列表选择事件发生在 列表 或 表格 中的选择正在更改或刚刚更改时。列表选择事件是从实现 ListSelectionModel
接口的对象中触发的。要获取表格的列表选择模型对象,可以使用 getSelectionModel
方法或 getColumnModel().getSelectionModel()
。
要检测列表选择事件,您需要在适当的列表选择模型对象上注册监听器。JList
类还提供了在列表本身上注册监听器的选项,而不是直接在列表选择模型上注册。
本节将介绍两个示例,展示如何监听选择模型上的列表选择事件。使用列表选择监听器的示例 列出了直接在列表上监听的示例。
在这两个示例中,您可以动态更改选择模式为三种支持的模式之一:
- 单选模式
- 单区间选择模式
- 多区间选择模式
这是 ListSelectionDemo 示例在列表中运行的图片:
试一试:
- 点击“启动”按钮以使用 Java™ Web Start 运行 ListSelectionDemo(下载 JDK 7 或更高版本)。或者,要自行编译和运行示例,请参考 示例索引。
- 选择和取消列表中的项目。选择项目所需的鼠标和键盘命令取决于外观。对于 Java 外观,单击左鼠标按钮开始选择,使用 shift 键连续扩展选择,使用 control 键不连续扩展选择。请注意,有两种类型的选择:Lead 和 Anchor。Lead 是焦点项目,Anchor 是高亮项目。当您按下 ctrl 键并上下移动时,Lead 选择会导致事件被触发,即使实际选择没有改变。拖动鼠标会根据列表选择模式移动或扩展选择。
这是 TableListSelectionDemo 示例在表格中运行的图片:
试试这个:
- 点击“启动”按钮以使用Java™ Web Start运行 TableListSelectionDemo(下载 JDK 7 或更高版本)。或者,要自行编译和运行示例,请参考示例索引。
- 在表格中选择和取消选择项目。选择项目所需的鼠标和键盘命令取决于外观。对于 Java 外观,单击左鼠标按钮开始选择,使用 Shift 键连续扩展选择,使用 Control 键不连续扩展选择。请注意,有两种类型的选择:Lead 和 Anchor。Lead 是焦点项目,Anchor 是突出显示的项目。当按下 ctrl 键并向上或向下移动时,主选择会导致事件被触发,即使实际选择没有更改。拖动鼠标会移动或扩展选择,具体取决于列表选择模式。
您可以在ListSelectionDemo.java
中找到 ListSelectionDemo 的整个程序,以及在TableListSelectionDemo.java
中找到 TableListSelectionDemo 的整个程序。
这是设置选择模型并向其添加监听器的ListSelectionDemo
中的代码:
*...//where the member variables are defined* JList list; *...//in the init method:* listSelectionModel = list.getSelectionModel(); listSelectionModel.addListSelectionListener( new SharedListSelectionHandler()); ...
这是适用于所有可能的选择模式的监听器代码:
class SharedListSelectionHandler implements ListSelectionListener { public void valueChanged(ListSelectionEvent e) { ListSelectionModel lsm = (ListSelectionModel)e.getSource(); int firstIndex = e.getFirstIndex(); int lastIndex = e.getLastIndex(); boolean isAdjusting = e.getValueIsAdjusting(); output.append("Event for indexes " + firstIndex + " - " + lastIndex + "; isAdjusting is " + isAdjusting + "; selected indexes:"); if (lsm.isSelectionEmpty()) { output.append(" <none>"); } else { // Find out which indexes are selected. int minIndex = lsm.getMinSelectionIndex(); int maxIndex = lsm.getMaxSelectionIndex(); for (int i = minIndex; i <= maxIndex; i++) { if (lsm.isSelectedIndex(i)) { output.append(" " + i); } } } output.append(newline); } }
这个valueChanged
方法显示了事件报告的第一个和最后一个索引,事件的isAdjusting
标志的值,以及当前选定的索引。
请注意,事件报告的第一个和最后一个索引指示了选择已更改的项目的包含范围。如果选择模式是多区间选择,则范围内的某些项目可能未更改。如果用户仍在操作选择,则isAdjusting
标志为true
,如果用户已完成更改选择,则为false
。
传递给valueChanged
的ListSelectionEvent
对象仅指示选择已更改。事件不包含有关当前选择的任何信息。因此,此方法查询选择模型以确定当前选择。
列表选择监听器 API
列表选择监听器接口
因为ListSelectionListener
只有一个方法,所以没有相应的适配器类。
方法 | 目的 |
valueChanged(ListSelectionEvent) | 响应选择更改时调用。 |
ListSelectionEvent API
方法 | 目的 |
Object getSource() (在java.util.EventObject 中) |
返回触发事件的对象。如果直接在列表上注册列表选择监听器,则每个事件的源是列表。否则,源是选择模型。 |
int getFirstIndex() | 返回选择值已更改的第一项的索引。请注意,对于多个间隔选择,保证第一个和最后一个项目已更改,但它们之间的项目可能没有更改。但是,当您按下 ctrl 键并向上或向下移动时,主选择会导致事件被触发,即使实际选择没有更改。 |
int getLastIndex() | 返回选择值已更改的最后一项的索引。请注意,对于多个间隔选择,保证第一个和最后一个项目已更改,但它们之间的项目可能没有更改。但是,当您按下 ctrl 键并上下移动时,主选择会导致事件被触发,即使实际选择没有更改。 |
boolean getValueIsAdjusting() | 如果选择仍在更改,则返回true 。许多列表选择监听器仅对选择的最终状态感兴趣,并且可以在此方法返回true 时忽略列表选择事件。 |
使用列表选择监听器的示例
下表列出了使用列表选择监听器的示例。
示例 | 描述位置 | 备注 |
ListSelectionDemo |
本节 | 报告列表上发生的所有列表选择事件。允许用户动态更改选择模式。 |
TableListSelectionDemo |
本节 | 报告表上发生的所有列表选择事件。允许用户动态更改选择模式。 |
ListDemo |
如何使用列表 | 监听单选列表上的事件(而不是其选择模型)。根据列表中是否选择了任何项目来启用或禁用按钮。 |
SplitPaneDemo |
如何使用列表 | 监听单选列表上的事件(而不是其选择模型)。 |
SimpleTableSelectionDemo |
如何使用表格 | 在一个表格上使用两种不同的列表选择监听器。一个监听器监听表格列上的列表选择事件,另一个监听器监听表格行上的列表选择事件。 |
如何编写鼠标监听器
原文:
docs.oracle.com/javase/tutorial/uiswing/events/mouselistener.html
鼠标事件通知用户使用鼠标(或类似输入设备)与组件交互时发生。鼠标事件发生在光标进入或退出组件的屏幕区域时,以及用户按下或释放鼠标按钮时。
跟踪光标的移动比跟踪其他鼠标事件需要更多的系统开销。这就是为什么鼠标移动事件被分为鼠标移动监听器类型(参见如何编写鼠标移动监听器)。
要跟踪鼠标滚轮事件,您可以注册一个鼠标滚轮监听器。有关更多信息,请参阅如何编写鼠标滚动监听器。
如果应用程序需要检测鼠标事件和鼠标移动事件,请使用MouseInputAdapter
类。该类实现了MouseInputListener
,这是一个方便的接口,实现了MouseListener
和MouseMotionListener
接口。但是,MouseInputListener
接口不实现MouseWheelListener
接口。
或者,使用相应的 AWT MouseAdapter
类,该类实现了MouseListener
、MouseMotionListener
和MouseWheelListener
接口。
以下示例显示了一个鼠标监听器。窗口顶部是一个空白区域(由名为BlankArea
的类实现)。鼠标监听器同时监听BlankArea
和其容器MouseEventDemo
的事件。每次发生鼠标事件时,在空白区域下方显示一个描述性消息。通过将光标移动到空白区域上方并偶尔按下鼠标按钮,您可以触发鼠标事件。
试试这个:
- 点击“启动”按钮以使用Java™ Web Start运行 MouseEventDemo(下载 JDK 7 或更高版本)。或者,要自行编译和运行示例,请参考示例索引。
- 将光标移动到窗口顶部的黄色矩形中。
您将看到一个或多个鼠标进入事件。 - 按住左鼠标按钮不要移动鼠标。
你会看到一个鼠标按下事件。你可能会看到一些额外的鼠标事件,比如鼠标退出然后鼠标进入。 - 释放鼠标按钮。
你会看到一个鼠标释放事件。如果你没有移动鼠标,将会接着是一个鼠标点击事件。 - 再次按住鼠标按钮,然后拖动鼠标,使光标最终移出窗口。释放鼠标按钮。
你会看到一个鼠标按下事件,接着是一个鼠标退出事件,然后是一个鼠标释放事件。你不会收到有关光标移动的通知。要获取鼠标移动事件,你需要实现一个鼠标移动监听器。
你可以在MouseEventDemo.java
和BlankArea.java
中找到演示代码。这里是演示的鼠标事件处理代码:
public class MouseEventDemo ... implements MouseListener { *//where initialization occurs:* //Register for mouse events on blankArea and the panel. blankArea.addMouseListener(this); addMouseListener(this); ... public void mousePressed(MouseEvent e) { saySomething("Mouse pressed; # of clicks: " + e.getClickCount(), e); } public void mouseReleased(MouseEvent e) { saySomething("Mouse released; # of clicks: " + e.getClickCount(), e); } public void mouseEntered(MouseEvent e) { saySomething("Mouse entered", e); } public void mouseExited(MouseEvent e) { saySomething("Mouse exited", e); } public void mouseClicked(MouseEvent e) { saySomething("Mouse clicked (# of clicks: " + e.getClickCount() + ")", e); } void saySomething(String eventDescription, MouseEvent e) { textArea.append(eventDescription + " detected on " + e.getComponent().getClass().getName() + "." + newline); } }
Java 中文官方教程 2022 版(二十五)(3)https://developer.aliyun.com/article/1486812