Java 中文官方教程 2022 版(二十五)(1)

简介: Java 中文官方教程 2022 版(二十五)

如何编写容器侦听器

原文:docs.oracle.com/javase/tutorial/uiswing/events/containerlistener.html

容器事件是由Container在组件被添加到容器或从容器中移除后触发的。这些事件仅用于通知 —— 组件成功添加或移除时不需要容器侦听器。

以下示例演示了容器事件。通过点击添加按钮移除按钮,您可以向窗口底部的面板添加按钮或从中移除按钮。每次向面板添加或移除按钮时,面板都会触发一个容器事件,并通知面板的容器侦听器。侦听器在窗口顶部的文本区域中显示描述性消息。



试一试:

  1. 点击启动按钮以使用Java™ Web Start运行 ContainerEventDemo(下载 JDK 7 或更高版本)。或者,要自行编译和运行示例,请参考示例索引。
  2. 点击标有添加按钮的按钮。
    您将看到一个按钮出现在窗口底部附近。容器侦听器对产生的组件添加事件做出反应,通过在窗口顶部显示"JButton #1 was added to javax.swing.JPanel"。
  3. 点击标有移除按钮的按钮。
    这将从面板中最近添加的按钮中移除一个,导致容器侦听器接收到组件移除事件。

您可以在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来表示其内容。文档事件发生在文档的内容以任何方式更改时。你将文档监听器附加到文本组件的文档上,而不是文本组件本身。有关更多信息,请参见实现文档过滤器。

以下示例演示了两个纯文本组件上的文档事件。



试一试:

  1. 点击“启动”按钮以使用Java™ Web Start运行 DocumentEventDemo(下载 JDK 7 或更高版本)。或者,要自行编译和运行示例,请参考示例索引。
  2. 在窗口左上角的文本字段或文本字段下方的文本区域中键入文本。
    每次键入字符时都会触发一个文档事件。
  3. 使用退格键删除文本。
    每次按退格键键入时都会触发一个文档事件。
  4. 选择文本,然后通过按退格键或使用CTRL-X(剪切)等键盘命令删除。
    整个删除操作会触发一个文档事件。
  5. 使用键盘命令如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);
    }
}

文档监听器不应修改文档的内容;在监听器被通知更改时,更改已经完成。相反,编写一个自定义文档,覆盖insertStringremove方法,或两者都覆盖。详细信息请参见监听文档更改。

文档监听器 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实例,如跟踪多个组件的焦点变化中所述。

以下示例演示了焦点事件。窗口显示了各种组件。在每个组件上注册了焦点监听器,报告每个焦点获得和失去事件。对于每个事件,涉及焦点变化的另一个组件,即对立组件,都会被报告。例如,当焦点从按钮转移到文本字段时,按钮会触发焦点失去事件(文本字段为对立组件),然后文本字段会触发焦点获得事件(按钮为对立组件)。焦点失去和焦点获得事件都可以是临时的。例如,当窗口失去焦点时会发生临时焦点失去事件。弹出菜单上会发生临时焦点获得事件。


运行示例

  1. 点击“启动”按钮以使用Java™ Web Start运行 FocusEventDemo(下载 JDK 7 或更高版本)。或者,要自行编译和运行示例,请参考示例索引。
  2. 在文本区域中会看到“焦点获得:JTextField”的消息 — 其“对立组件”为 null,因为它是第一个获得焦点的组件。
  3. 点击标签。因为标签默认情况下无法获得焦点,所以不会发生任何事情。
  4. 点击下拉框。文本字段会触发一个焦点丢失事件,下拉框会触发一个焦点获得事件。下拉框现在显示它拥有焦点,可能会有一个虚线围绕文本的方式来表示。这种表示方式取决于外观和感觉。
    注意,当焦点从一个组件转移到另一个组件时,第一个组件会在第二个组件触发焦点获得事件之前触发焦点丢失事件。
  5. 从下拉框的菜单中选择一个选项。再次点击下拉框。注意到没有焦点事件报告。只要用户操作同一组件,焦点就会保持在该组件上。
  6. 点击打印焦点事件的文本区域。什么也不会发生,因为文本区域已经被设置为不可点击,使用了setRequestFocusEnabled(false)
  7. 点击文本字段以将焦点返回到初始组件。
  8. 在键盘上按下 Tab 键。焦点移动到下拉框,并跳过标签。
  9. 再次按下 Tab 键。焦点移动到按钮上。
  10. 点击另一个窗口,使得 FocusEventDemo 窗口失去焦点。按钮会生成一个临时的焦点丢失事件。
  11. 点击 FocusEventDemo 窗口的顶部。按钮会触发一个焦点获得事件。
  12. 在键盘上再次按下 Tab 键。焦点移动到列表上。
  13. 再次按下 Tab 键。焦点移动到文本区域。
    注意,即使你不能点击文本区域,你仍然可以通过 Tab 键到达它。这样做是为了让使用辅助技术的用户能够确定组件的存在以及其包含的内容。演示通过在文本区域上调用setRequestFocusEnabled(false)来禁用点击焦点,同时保留其通过 Tab 键获得焦点的能力。演示可以使用setFocusable(false)来真正将文本区域从焦点循环中移除,但这样做会使使用辅助技术的用户无法访问该组件。
  14. 再次按下 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接口。

下图中显示的应用程序演示了内部框架事件。该应用程序监听来自事件生成器框架的内部框架事件,显示描述每个事件的消息。



试试这个:

  1. 点击“启动”按钮以使用Java™ Web Start运行 InternalFrameEventDemo(下载 JDK 7 或更高版本)。或者,要自行编译和运行示例,请参考示例索引。
  2. 点击显示内部框架按钮,打开事件生成器内部框架。
    在显示区域中应该看到一个“内部框架已打开”的消息。
  3. 尝试各种操作,看看会发生什么。例如,点击事件生成器以激活它。点击事件监视器以使事件生成器停用。点击事件生成器的装饰以将窗口图标化、最大化、最小化和关闭。
    查看如何编写窗口监听器以获取有关您将看到的事件类型的信息。

这是处理内部框架事件的代码:

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在用户关闭时隐藏窗口。您可以使用JInternalFramesetDefaultCloseOperation方法指定另一个选项,该选项必须是DISPOSE_ON_CLOSEDO_NOTHING_ON_CLOSE(都在WindowConstants中定义,JInternalFrame实现了该接口)。或者通过在内部框架的监听器中实现internalFrameClosing方法,您可以添加自定义行为(例如弹出对话框或保存数据)以响应内部框架的关闭。
internalFrameClosed(InternalFrameEvent) 在监听的内部框架被销毁后立即调用。
internalFrameIconified(InternalFrameEvent) internalFrameDeiconified(InternalFrameEvent) 在监听的内部框架被图标化或取消图标化后立即调用。
internalFrameActivated(InternalFrameEvent) internalFrameDeactivated(InternalFrameEvent) 在监听的内部框架被激活或停用后立即调用。

每个内部框架事件方法都有一个参数:一个InternalFrameEvent对象。InternalFrameEvent类定义了没有通用用途的方法。要获取触发事件的内部框架,使用getSource方法,该方法是InternalFrameEventjava.util.EventObject继承而来。

使用内部框架监听器的示例

目前没有其他源文件包含内部框架监听器。但是,内部框架监听器与WindowListener非常相似,几个 Swing 程序都有窗口监听器:

示例 描述位置 注释
InternalFrameEventDemo 本节 报告发生在一个内部框架上的所有内部框架事件,以演示触发内部框架事件的情况。
DialogDemo 文本组件功能 CustomDialog.java 使用 setDefaultCloseOperation 而不是窗口监听器来确定用户关闭窗口时要采取的操作。
SliderDemo 如何使用滑块 监听窗口最小化和最大化事件,以便在窗口不可见时停止动画。

Java 中文官方教程 2022 版(二十五)(2)https://developer.aliyun.com/article/1486808

相关文章
|
2天前
|
Web App开发 JavaScript 前端开发
《手把手教你》系列技巧篇(三十九)-java+ selenium自动化测试-JavaScript的调用执行-上篇(详解教程)
【5月更文挑战第3天】本文介绍了如何在Web自动化测试中使用JavaScript执行器(JavascriptExecutor)来完成Selenium API无法处理的任务。首先,需要将WebDriver转换为JavascriptExecutor对象,然后通过executeScript方法执行JavaScript代码。示例用法包括设置JS代码字符串并调用executeScript。文章提供了两个实战场景:一是当时间插件限制输入时,用JS去除元素的readonly属性;二是处理需滚动才能显示的元素,利用JS滚动页面。还给出了一个滚动到底部的代码示例,并提供了详细步骤和解释。
31 10
|
2天前
|
Java 测试技术 Python
《手把手教你》系列技巧篇(三十六)-java+ selenium自动化测试-单选和多选按钮操作-番外篇(详解教程)
【4月更文挑战第28天】本文简要介绍了自动化测试的实战应用,通过一个在线问卷调查(<https://www.sojump.com/m/2792226.aspx/>)为例,展示了如何遍历并点击问卷中的选项。测试思路包括找到单选和多选按钮的共性以定位元素,然后使用for循环进行点击操作。代码设计方面,提供了Java+Selenium的示例代码,通过WebDriver实现自动答题。运行代码后,可以看到控制台输出和浏览器的相应动作。文章最后做了简单的小结,强调了本次实践是对之前单选多选操作的巩固。
25 0
|
17小时前
|
算法 Java Python
保姆级Java入门练习教程,附代码讲解,小白零基础入门必备
保姆级Java入门练习教程,附代码讲解,小白零基础入门必备
|
20小时前
|
Web App开发 JavaScript 测试技术
《手把手教你》系列技巧篇(四十五)-java+ selenium自动化测试-web页面定位toast-上篇(详解教程)
【5月更文挑战第9天】本文介绍了在Appium中处理App自动化测试中遇到的Toast元素定位的方法。Toast在Web UI测试中也常见,通常作为轻量级反馈短暂显示。文章提供了两种定位Toast元素的技巧.
10 0
|
2天前
|
Web App开发 缓存 前端开发
《手把手教你》系列技巧篇(四十四)-java+ selenium自动化测试-处理https 安全问题或者非信任站点-下篇(详解教程)
【5月更文挑战第8天】这篇文档介绍了如何在IE、Chrome和Firefox浏览器中处理不信任证书的问题。作者北京-宏哥分享了如何通过编程方式跳过浏览器的证书警告,直接访问不受信任的HTTPS网站。文章分为几个部分,首先简要介绍了问题背景,然后详细讲解了在Chrome浏览器中的两种方法,包括代码设计和运行效果,并给出了其他浏览器的相关信息和参考资料。最后,作者总结了处理此类问题的一些通用技巧。
16 2
|
2天前
|
Java Android开发
【Java开发指南 | 第十八篇】Eclipse安装教程
【Java开发指南 | 第十八篇】Eclipse安装教程
11 2
|
2天前
|
Web App开发 JavaScript 前端开发
《手把手教你》系列技巧篇(四十三)-java+ selenium自动化测试-处理https 安全问题或者非信任站点-上篇(详解教程)
【5月更文挑战第7天】本文介绍了如何在Java+Selenium自动化测试中处理浏览器对不信任证书的处理方法,特别是针对IE、Chrome和Firefox浏览器。在某些情况下,访问HTTPS网站时会遇到证书不可信的警告,但可以通过编程方式跳过这些警告。
13 1
|
2天前
|
前端开发 Java 测试技术
《手把手教你》系列技巧篇(四十二)-java+ selenium自动化测试 - 处理iframe -下篇(详解教程)
【5月更文挑战第6天】本文介绍了如何使用Selenium处理含有iframe的网页。作者首先解释了iframe是什么,即HTML中的一个框架,用于在一个页面中嵌入另一个页面。接着,通过一个实战例子展示了在QQ邮箱登录页面中,由于输入框存在于iframe内,导致直接定位元素失败。作者提供了三种方法来处理这种情况:1)通过id或name属性切换到iframe;2)使用webElement对象切换;3)通过索引切换。最后,给出了相应的Java代码示例,并提醒读者根据iframe的实际情况选择合适的方法进行切换和元素定位。
9 0
|
2天前
|
前端开发 测试技术 Python
《手把手教你》系列技巧篇(四十一)-java+ selenium自动化测试 - 处理iframe -上篇(详解教程)
【5月更文挑战第5天】本文介绍了HTML中的`iframe`标签,它用于在网页中嵌套其他网页。`iframe`常用于加载外部内容或网站的某个部分,以实现页面美观。文章还讲述了使用Selenium自动化测试时如何处理`iframe`,通过`switchTo().frame()`方法进入`iframe`,完成相应操作,然后使用`switchTo().defaultContent()`返回主窗口。此外,文章提供了一个包含`iframe`的HTML代码示例,并给出了一个简单的自动化测试代码实战,演示了如何在`iframe`中输入文本。
17 3
|
2天前
|
JavaScript 前端开发 Java
《手把手教你》系列技巧篇(四十)-java+ selenium自动化测试-JavaScript的调用执行-下篇(详解教程)
【5月更文挑战第4天】本文介绍了如何使用JavaScriptExecutor在自动化测试中实现元素高亮显示。通过创建并执行JS代码,可以改变元素的样式,例如设置背景色和边框,以突出显示被操作的元素。文中提供了一个Java示例,展示了如何在Selenium中使用此方法,并附有代码截图和运行效果展示。该技术有助于跟踪和理解测试过程中的元素交互。
10 0