如何编写容器侦听器
原文:
docs.oracle.com/javase/tutorial/uiswing/events/containerlistener.html
容器事件是由Container
在组件被添加到容器或从容器中移除后触发的。这些事件仅用于通知 —— 组件成功添加或移除时不需要容器侦听器。
以下示例演示了容器事件。通过点击添加按钮或移除按钮,您可以向窗口底部的面板添加按钮或从中移除按钮。每次向面板添加或移除按钮时,面板都会触发一个容器事件,并通知面板的容器侦听器。侦听器在窗口顶部的文本区域中显示描述性消息。
试一试:
- 点击启动按钮以使用Java™ Web Start运行 ContainerEventDemo(下载 JDK 7 或更高版本)。或者,要自行编译和运行示例,请参考示例索引。
- 点击标有添加按钮的按钮。
您将看到一个按钮出现在窗口底部附近。容器侦听器对产生的组件添加事件做出反应,通过在窗口顶部显示"JButton #1 was added to javax.swing.JPanel"。 - 点击标有移除按钮的按钮。
这将从面板中最近添加的按钮中移除一个,导致容器侦听器接收到组件移除事件。
您可以在ContainerEventDemo.java
中找到演示的代码。以下是演示的容器事件处理代码:
public class ContainerEventDemo ... implements ContainerListener ... { *...//where initialization occurs:* buttonPanel = new JPanel(new GridLayout(1,1)); buttonPanel.addContainerListener(this); ... public void componentAdded(ContainerEvent e) { displayMessage(" added to ", e); } public void componentRemoved(ContainerEvent e) { displayMessage(" removed from ", e); } void displayMessage(String action, ContainerEvent e) { display.append(((JButton)e.getChild()).getText() + " was" + action + e.getContainer().getClass().getName() + newline); } ... }
容器侦听器 API
容器侦听器接口
相应的适配器类是ContainerAdapter
。
方法 | 目的 |
componentAdded(ContainerEvent) | 在被监听容器中的组件被添加后调用。 |
componentRemoved(ContainerEvent) | 在被监听容器中的组件被移除后调用。 |
ContainerEvent 类
方法 | 目的 |
获取子组件 getChild() | 返回触发此事件的组件的添加或移除。 |
获取容器 getContainer() | 返回触发此事件的容器。您可以使用这个方法代替getSource 方法。 |
使用容器监听器的示例
以下表格列出了使用容器监听器的示例。
示例 | 描述位置 | 备注 |
ContainerEventDemo |
本节 | 报告发生在单个面板上的所有容器事件,以展示触发容器事件的情况。 |
如何编写文档监听器
原文:
docs.oracle.com/javase/tutorial/uiswing/events/documentlistener.html
Swing 文本组件使用Document
来表示其内容。文档事件发生在文档的内容以任何方式更改时。你将文档监听器附加到文本组件的文档上,而不是文本组件本身。有关更多信息,请参见实现文档过滤器。
以下示例演示了两个纯文本组件上的文档事件。
试一试:
- 点击“启动”按钮以使用Java™ Web Start运行 DocumentEventDemo(下载 JDK 7 或更高版本)。或者,要自行编译和运行示例,请参考示例索引。
- 在窗口左上角的文本字段或文本字段下方的文本区域中键入文本。
每次键入字符时都会触发一个文档事件。 - 使用退格键删除文本。
每次按退格键键入时都会触发一个文档事件。 - 选择文本,然后通过按退格键或使用
CTRL-X
(剪切)等键盘命令删除。
整个删除操作会触发一个文档事件。 - 使用键盘命令如
CTRL-C
(复制)和CTRL-V
(粘贴)将文本从一个文本组件复制到另一个文本组件。
无论粘贴的文本长度如何,整个粘贴操作都会触发一个文档事件。如果在发出粘贴命令之前在目标文本组件中选择文本,则会触发额外的文档事件,因为首先删除所选文本。
你可以在DocumentEventDemo.java
中找到演示代码。以下是演示文档事件处理代码:
public class DocumentEventDemo ... { *...//where initialization occurs:* textField = new JTextField(20); textField.addActionListener(new MyTextActionListener()); textField.getDocument().addDocumentListener(new MyDocumentListener()); textField.getDocument().putProperty("name", "Text Field"); textArea = new JTextArea(); textArea.getDocument().addDocumentListener(new MyDocumentListener()); textArea.getDocument().putProperty("name", "Text Area"); ... class MyDocumentListener implements DocumentListener { String newline = "\n"; public void insertUpdate(DocumentEvent e) { updateLog(e, "inserted into"); } public void removeUpdate(DocumentEvent e) { updateLog(e, "removed from"); } public void changedUpdate(DocumentEvent e) { //Plain text components do not fire these events } public void updateLog(DocumentEvent e, String action) { Document doc = (Document)e.getDocument(); int changeLength = e.getLength(); displayArea.append( changeLength + " character" + ((changeLength == 1) ? " " : "s ") + action + doc.getProperty("name") + "." + newline + " Text length = " + doc.getLength() + newline); } }
文档监听器不应修改文档的内容;在监听器被通知更改时,更改已经完成。相反,编写一个自定义文档,覆盖insertString
或remove
方法,或两者都覆盖。详细信息请参见监听文档更改。
文档监听器 API
文档监听器接口
DocumentListener
没有适配器类。
方法 | 目的 |
changedUpdate(DocumentEvent) | 当监听文档中的一些文本样式发生变化时调用。这种事件仅从StyledDocument 中触发 — PlainDocument 不会触发这些事件。 |
insertUpdate(DocumentEvent) | 当文本插入到监听文档中时调用。 |
removeUpdate(DocumentEvent) | 当从监听文档中删除文本时调用。 |
文档事件接口
每个文档事件方法都会传递一个实现DocumentEvent
接口的对象。通常,这是AbstractDocument
中定义的DefaultDocumentEvent
的实例。
方法 | 目的 |
获取文档的 Document 对象 | 返回触发事件的文档。请注意,DocumentEvent 接口不继承自EventObject 。因此,它不继承getSource 方法。 |
获取长度的 int 方法 | 返回更改的长度。 |
获取偏移量的 int 方法 | 返回更改的第一个字符在文档中的位置。 |
获取更改的 ElementChange 方法 | 返回文档中已更改的元素及其详细信息。ElementChange 是在DocumentEvent 接口中定义的一个接口。 |
获取类型的 EventType 方法 | 返回发生的更改类型。EventType 是在DocumentEvent 接口中定义的一个类,列举了文档上可能发生的更改类型:插入文本、删除文本和更改文本样式。 |
使用文档监听器的示例
以下表列出了使用文档监听器的示例。
示例 | 描述位置 | 注意事项 |
DocumentEventDemo |
本节 | 报告文本字段和文本区域上发生的所有文档事件。一个监听器同时监听两个文本组件,并使用文档上的客户端属性来确定哪个组件触发了事件。 |
TextComponentDemo |
监听文档变化 | 每当被监听文档中的文本发生变化时更新变更日志。本示例中的文档支持样式文本,因此在本示例中调用changedUpdate 。需要额外的源文件:DocumentSizeFilter |
如何编写焦点监听器
原文:
docs.oracle.com/javase/tutorial/uiswing/events/focuslistener.html
焦点事件在组件获得或失去键盘焦点时触发。无论焦点变化是通过鼠标、键盘还是程序化操作,都是如此。要熟悉基本的焦点概念或获取关于焦点的详细信息,请参阅如何使用焦点子系统。
本节解释了如何通过在特定组件上注册FocusListener
实例来获取该组件的焦点事件。要仅获取窗口的焦点,请实现WindowFocusListener
实例。要获取多个组件的焦点状态,请考虑在KeyboardFocusManager
类上实现PropertyChangeListener
实例,如跟踪多个组件的焦点变化中所述。
以下示例演示了焦点事件。窗口显示了各种组件。在每个组件上注册了焦点监听器,报告每个焦点获得和失去事件。对于每个事件,涉及焦点变化的另一个组件,即对立组件,都会被报告。例如,当焦点从按钮转移到文本字段时,按钮会触发焦点失去事件(文本字段为对立组件),然后文本字段会触发焦点获得事件(按钮为对立组件)。焦点失去和焦点获得事件都可以是临时的。例如,当窗口失去焦点时会发生临时焦点失去事件。弹出菜单上会发生临时焦点获得事件。
运行示例
- 点击“启动”按钮以使用Java™ Web Start运行 FocusEventDemo(下载 JDK 7 或更高版本)。或者,要自行编译和运行示例,请参考示例索引。
- 在文本区域中会看到“焦点获得:JTextField”的消息 — 其“对立组件”为 null,因为它是第一个获得焦点的组件。
- 点击标签。因为标签默认情况下无法获得焦点,所以不会发生任何事情。
- 点击下拉框。文本字段会触发一个焦点丢失事件,下拉框会触发一个焦点获得事件。下拉框现在显示它拥有焦点,可能会有一个虚线围绕文本的方式来表示。这种表示方式取决于外观和感觉。
注意,当焦点从一个组件转移到另一个组件时,第一个组件会在第二个组件触发焦点获得事件之前触发焦点丢失事件。 - 从下拉框的菜单中选择一个选项。再次点击下拉框。注意到没有焦点事件报告。只要用户操作同一组件,焦点就会保持在该组件上。
- 点击打印焦点事件的文本区域。什么也不会发生,因为文本区域已经被设置为不可点击,使用了
setRequestFocusEnabled(false)
。 - 点击文本字段以将焦点返回到初始组件。
- 在键盘上按下 Tab 键。焦点移动到下拉框,并跳过标签。
- 再次按下 Tab 键。焦点移动到按钮上。
- 点击另一个窗口,使得 FocusEventDemo 窗口失去焦点。按钮会生成一个临时的焦点丢失事件。
- 点击 FocusEventDemo 窗口的顶部。按钮会触发一个焦点获得事件。
- 在键盘上再次按下 Tab 键。焦点移动到列表上。
- 再次按下 Tab 键。焦点移动到文本区域。
注意,即使你不能点击文本区域,你仍然可以通过 Tab 键到达它。这样做是为了让使用辅助技术的用户能够确定组件的存在以及其包含的内容。演示通过在文本区域上调用setRequestFocusEnabled(false)
来禁用点击焦点,同时保留其通过 Tab 键获得焦点的能力。演示可以使用setFocusable(false)
来真正将文本区域从焦点循环中移除,但这样做会使使用辅助技术的用户无法访问该组件。 - 再次按下 Tab 键。焦点从列表返回到文本字段。你刚刚完成了一个焦点循环。请参阅介绍中的如何使用焦点子系统来讨论焦点术语和概念。
这个演示的完整代码在FocusEventDemo.java
文件中。以下代码片段代表了焦点事件处理机制:
public class FocusEventDemo ... implements FocusListener ... { public FocusEventDemo() { ... JTextField textField = new JTextField("A TextField"); textField.addFocusListener(this); ... JLabel label = new JLabel("A Label"); label.addFocusListener(this); ... JComboBox comboBox = new JComboBox(vector); comboBox.addFocusListener(this); ... JButton button = new JButton("A Button"); button.addFocusListener(this); ... JList list = new JList(listVector); list.setSelectedIndex(1); //It's easier to see the focus change //if an item is selected. list.addFocusListener(this); JScrollPane listScrollPane = new JScrollPane(list); ... //Set up the area that reports focus-gained and focus-lost events. display = new JTextArea(); display.setEditable(false); //The method setRequestFocusEnabled prevents a //component from being clickable, but it can still //get the focus through the keyboard - this ensures //user accessibility. display.setRequestFocusEnabled(false); display.addFocusListener(this); JScrollPane displayScrollPane = new JScrollPane(display); ... } ... public void focusGained(FocusEvent e) { displayMessage("Focus gained", e); } public void focusLost(FocusEvent e) { displayMessage("Focus lost", e); } void displayMessage(String prefix, FocusEvent e) { display.append(prefix + (e.isTemporary() ? " (temporary):" : ":") + e.getComponent().getClass().getName() + "; Opposite component: " + (e.getOppositeComponent() != null ? e.getOppositeComponent().getClass().getName() : "null") + newline); } ... }
焦点监听器 API
焦点监听器接口
对应的适配器类是FocusAdapter
。
方法 | 目的 |
focusGained(FocusEvent) | 在被监听组件获得焦点后调用。 |
focusLost(FocusEvent) | 在监听到的组件失去焦点后调用。 |
焦点事件 API
方法 | 目的 |
boolean isTemporary() | 如果焦点丢失或获得事件是临时的,则返回true 。 |
Component getComponent() (在 java.awt.event.ComponentEvent 中) |
返回触发焦点事件的组件。 |
Component getOppositeComponent() | 返回焦点变化中涉及的另一个组件。对于FOCUS_GAINED 事件,这是失去焦点的组件。对于FOCUS_LOST 事件,这是获得焦点的组件。如果焦点变化涉及本机应用程序、不同 VM 或上下文中的 Java 应用程序,或没有其他组件,则返回null 。 |
使用焦点监听器的示例
以下表格列出了使用焦点监听器的示例。
示例 | 描述位置 | 备注 |
FocusEventDemo |
本节 | 报告发生在几个组件上的所有焦点事件,以演示触发焦点事件的情况。 |
TrackFocusDemo |
如何使用焦点子系统 | 自定义组件Picture 实现了焦点监听器,当它是当前焦点所有者时,会在组件周围绘制红色边框。 |
如何编写内部框架监听器
原文:
docs.oracle.com/javase/tutorial/uiswing/events/internalframelistener.html
InternalFrameListener
类似于WindowListener
。与窗口监听器类似,内部框架监听器监听发生在“窗口”首次显示、销毁、图标化、取消图标化、激活或停用时的事件。在使用内部框架监听器之前,请熟悉如何编写窗口监听器中的WindowListener
接口。
下图中显示的应用程序演示了内部框架事件。该应用程序监听来自事件生成器框架的内部框架事件,显示描述每个事件的消息。
试试这个:
- 点击“启动”按钮以使用Java™ Web Start运行 InternalFrameEventDemo(下载 JDK 7 或更高版本)。或者,要自行编译和运行示例,请参考示例索引。
- 点击显示内部框架按钮,打开事件生成器内部框架。
在显示区域中应该看到一个“内部框架已打开”的消息。 - 尝试各种操作,看看会发生什么。例如,点击事件生成器以激活它。点击事件监视器以使事件生成器停用。点击事件生成器的装饰以将窗口图标化、最大化、最小化和关闭。
查看如何编写窗口监听器以获取有关您将看到的事件类型的信息。
这是处理内部框架事件的代码:
public class InternalFrameEventDemo ... implements InternalFrameListener ... { ... public void internalFrameClosing(InternalFrameEvent e) { displayMessage("Internal frame closing", e); } public void internalFrameClosed(InternalFrameEvent e) { displayMessage("Internal frame closed", e); listenedToWindow = null; } public void internalFrameOpened(InternalFrameEvent e) { displayMessage("Internal frame opened", e); } public void internalFrameIconified(InternalFrameEvent e) { displayMessage("Internal frame iconified", e); } public void internalFrameDeiconified(InternalFrameEvent e) { displayMessage("Internal frame deiconified", e); } public void internalFrameActivated(InternalFrameEvent e) { displayMessage("Internal frame activated", e); } public void internalFrameDeactivated(InternalFrameEvent e) { displayMessage("Internal frame deactivated", e); } void displayMessage(String prefix, InternalFrameEvent e) { String s = prefix + ": " + e.getSource(); display.append(s + newline); } public void actionPerformed(ActionEvent e) { if (SHOW.equals(e.getActionCommand())) { ... if (listenedToWindow == null) { listenedToWindow = new JInternalFrame("Event Generator", true, //resizable true, //closable true, //maximizable true); //iconifiable //We want to reuse the internal frame, so we need to //make it hide (instead of being disposed of, which is //the default) when the user closes it. listenedToWindow.setDefaultCloseOperation( WindowConstants.HIDE_ON_CLOSE); listenedToWindow.addInternalFrameListener(this); ... } } ... } }
内部框架监听器 API
内部框架监听器接口
相应的适配器类是InternalFrameAdapter
。
方法 | 目的 |
internalFrameOpened(InternalFrameEvent) | 在监听的内部框架首次显示后调用。 |
internalFrameClosing(InternalFrameEvent) | 响应用户请求关闭监听的内部框架时调用。默认情况下,JInternalFrame 在用户关闭时隐藏窗口。您可以使用JInternalFrame 的setDefaultCloseOperation 方法指定另一个选项,该选项必须是DISPOSE_ON_CLOSE 或DO_NOTHING_ON_CLOSE (都在WindowConstants 中定义,JInternalFrame 实现了该接口)。或者通过在内部框架的监听器中实现internalFrameClosing 方法,您可以添加自定义行为(例如弹出对话框或保存数据)以响应内部框架的关闭。 |
internalFrameClosed(InternalFrameEvent) | 在监听的内部框架被销毁后立即调用。 |
internalFrameIconified(InternalFrameEvent) internalFrameDeiconified(InternalFrameEvent) | 在监听的内部框架被图标化或取消图标化后立即调用。 |
internalFrameActivated(InternalFrameEvent) internalFrameDeactivated(InternalFrameEvent) | 在监听的内部框架被激活或停用后立即调用。 |
每个内部框架事件方法都有一个参数:一个InternalFrameEvent
对象。InternalFrameEvent
类定义了没有通用用途的方法。要获取触发事件的内部框架,使用getSource
方法,该方法是InternalFrameEvent
从java.util.EventObject
继承而来。
使用内部框架监听器的示例
目前没有其他源文件包含内部框架监听器。但是,内部框架监听器与WindowListener
非常相似,几个 Swing 程序都有窗口监听器:
示例 | 描述位置 | 注释 |
InternalFrameEventDemo |
本节 | 报告发生在一个内部框架上的所有内部框架事件,以演示触发内部框架事件的情况。 |
DialogDemo |
文本组件功能 | CustomDialog.java 使用 setDefaultCloseOperation 而不是窗口监听器来确定用户关闭窗口时要采取的操作。 |
SliderDemo |
如何使用滑块 | 监听窗口最小化和最大化事件,以便在窗口不可见时停止动画。 |
Java 中文官方教程 2022 版(二十五)(2)https://developer.aliyun.com/article/1486808