如何编写窗口侦听器

本节说明如何实现与窗口相关的三种事件处理程序:WindowListenerWindowFocusListenerWindowStateListener。所有三个侦听器都处理WindowEvent个对象。这三个事件处理程序中的方法均由抽象WindowAdapter类实现。

当适当的侦听器已在窗口(例如framedialog)上注册后,窗口事件或状态发生后立即触发窗口事件。如果该窗口收到键盘 Importing,则该窗口被视为“焦点所有者”。

以下窗口活动或状态可以在窗口事件之前:

  • 打开一个窗口—第一次显示一个窗口。

  • 关闭窗口—从屏幕上删除窗口。

  • 图标化窗口—将窗口缩小为桌面上的图标。

  • 取消图标化窗口-将窗口恢复为其原始大小。

  • 焦点窗口-包含“焦点所有者”的窗口。

  • 激活的窗口(框架或对话框)-此窗口是焦点窗口或拥有焦点窗口。

  • 停用窗口-该窗口失去了焦点。有关焦点的更多信息,请参见AWT Focus 子系统规范。

  • 最大化窗口—在垂直方向,水平方向或两个方向上都将窗口的大小增加到最大允许大小。

WindowListenerinterface定义用于处理大多数窗口事件的方法,例如用于打开和关闭窗口,激活和停用窗口以及图标化和去图标化的事件。

其他两个窗口侦听器interface是WindowFocusListenerWindowStateListenerWindowFocusListener包含一些方法,用于检测窗口何时成为焦点所有者或窗口何时失去焦点所有者状态。 WindowStateListener具有检测窗口状态变化的单一方法,例如当窗口被图标化,去图标化,最大化或恢复正常时。

尽管您可以使用WindowListener方法来检测某些窗口状态(例如图标化),但是WindowStateListener可能更受欢迎的原因有两个:它只有一种方法可供您实现,并且它支持最大化。

Note:

并非所有的窗口 管理 器/本机平台都支持所有窗口状态。 java.awt.Toolkit方法isFrameStateSupported(int)可用于确定特定窗口 管理 器是否支持特定窗口状态。本节稍后介绍的 WindowEventDemo 示例说明如何使用此方法。

窗口侦听器通常用于实现自定义的关闭窗口行为。例如,窗口侦听器用于在关闭窗口之前保存数据,或在最后一个窗口关闭时退出程序。

用户不一定需要实现窗口侦听器来指定用户在关闭窗口时应执行的操作。默认情况下,当用户关闭窗口时,该窗口变为不可见。若要指定不同的行为,请使用JFrameJDialog类的setDefaultCloseOperation方法。要实现关闭窗口的处理程序,请使用setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE)方法启用窗口侦听器以提供所有关闭窗口的职责。有关如何使用setDefaultCloseOperation的详细信息,请参见响应窗口关闭事件

当处置 Java 虚拟机(VM)中的最后一个可显示窗口时,VM 可能会终止。但是请注意,程序自动退出之前可能会有延迟,并且在某些情况下程序可能会 continue 运行。使用System.exit(int)显式退出程序更快,更安全。有关更多信息,请参见AWT 线程问题

窗口侦听器通常还用于在图标化窗口时停止线程并释放资源,并在取消图标化窗口时再次启动。这避免了不必要地使用处理器或其他资源。例如,当对包含动画的窗口进行图标化时,它应停止其动画线程并释放所有大缓冲区。当窗口去图标化后,它可以再次启动线程并重新创建缓冲区。

下面的示例演示窗口事件。不可编辑的文本区域报告由其窗口触发的所有窗口事件。该演示实现了WindowListenerWindowFocusListenerWindowStateListenerinterface中的所有方法。您可以在WindowEventDemo.java中找到该演示的代码。

WindowEventDemo.html

Try this:

  • 单击启动按钮以使用Java™Web 开始(下载 JDK 7 或更高版本)运行 WindowEventDemo。另外,要自己编译和运行示例,请查阅example index

  • 出现窗口时,已经显示了几条消息。一行报告您的窗口 管理 器是否支持 MAXIMIZED_BOTH。如果窗口 管理 器不支持其他窗口状态,则也会报告此情况。接下来,显示几行,报告该窗口的窗口侦听器已接收到窗口打开,激活和获得焦点事件。窗口中显示的所有消息也将发送到标准输出。

  • 单击另一个窗口。将显示“窗口失去焦点”和“窗口已停用”消息。如果此窗口不是框架或对话框,它将接收已激活或已禁用的事件。

  • 单击 WindowEventDemo 窗口。您将看到“窗口激活”和“窗口获得焦点”消息。

  • 使用窗口控件来图标化窗口。显示两个图标化消息,一个来自窗口侦听器,另一个来自窗口状态侦听器。除非您查看标准输出,否则将不显示该窗口,消息将不会显示。还报告了窗口停用和窗口丢失焦点事件。

  • 取消图标化窗口。显示两个去图标化消息,一个来自窗口侦听器,另一个来自窗口状态侦听器。 WindowStateListener类中的windowStateChanged方法提供的信息与WindowListener类中的windowIconifiedwindowDeiconified方法获得的信息相同。还报告了窗口激活和窗口获取焦点事件。

  • 如果您的外观提供了最大化窗口的方法,请这样做。请注意,在某些窗口 管理 器上运行的某些外观(例如 dtwm 上的 Java 外观)提供了最大化窗口的方法,但未报告任何事件。这是因为 dtwm 通过调整窗口大小来模拟最大化,但这不是 true 的最大化事件。某些外观提供了一种在垂直或水平方向上最大化窗口的方法。try使用您的窗口控件,以查看可用的选项。

  • 使用窗口控件关闭窗口。显示关闭窗口消息。窗口关闭后,窗口关闭消息将发送到标准输出。

这是演示的窗口事件处理代码:

public class WindowEventDemo extends JFrame implements WindowListener,
                                            WindowFocusListener,
                                            WindowStateListener {
    ...
    static WindowEventDemo frame = new WindowEventDemo("WindowEventDemo");
    JTextArea display;
    ...

    private void addComponentsToPane() {
        display = new JTextArea();
        display.setEditable(false);
        JScrollPane scrollPane = new JScrollPane(display);
        scrollPane.setPreferredSize(new Dimension(500, 450));
        getContentPane().add(scrollPane, BorderLayout.CENTER);
        
        addWindowListener(this);
        addWindowFocusListener(this);
        addWindowStateListener(this);
        
        checkWM();
    }
    
    public WindowEventDemo(String name) {
        super(name);
    }

    //Some window managers don't support all window states.
  
    public void checkWM() {
        Toolkit tk = frame.getToolkit();
        if (!(tk.isFrameStateSupported(Frame.ICONIFIED))) {
            displayMessage(
                    "Your window manager doesn't support ICONIFIED.");
        }  else displayMessage(
                "Your window manager supports ICONIFIED.");
        if (!(tk.isFrameStateSupported(Frame.MAXIMIZED_VERT))) {
            displayMessage(
                    "Your window manager doesn't support MAXIMIZED_VERT.");
        }  else displayMessage(
                "Your window manager supports MAXIMIZED_VERT.");
        if (!(tk.isFrameStateSupported(Frame.MAXIMIZED_HORIZ))) {
            displayMessage(
                    "Your window manager doesn't support MAXIMIZED_HORIZ.");
        } else displayMessage(
                "Your window manager supports MAXIMIZED_HORIZ.");
        if (!(tk.isFrameStateSupported(Frame.MAXIMIZED_BOTH))) {
            displayMessage(
                    "Your window manager doesn't support MAXIMIZED_BOTH.");
        } else {
            displayMessage(
                    "Your window manager supports MAXIMIZED_BOTH.");
        }
    }

    public void windowClosing(WindowEvent e) {
        displayMessage("WindowListener method called: windowClosing.");
        //A pause so user can see the message before
        //the window actually closes.
        ActionListener task = new ActionListener() {
            boolean alreadyDisposed = false;
            public void actionPerformed(ActionEvent e) {
                if (frame.isDisplayable()) {
                    alreadyDisposed = true;
                    frame.dispose();
                }
            }
        };
        Timer timer = new Timer(500, task); //fire every half second
        timer.setInitialDelay(2000);        //first delay 2 seconds
        timer.setRepeats(false);
        timer.start();
    }

    public void windowClosed(WindowEvent e) {
        //This will only be seen on standard output.
        displayMessage("WindowListener method called: windowClosed.");
    }

    public void windowOpened(WindowEvent e) {
        displayMessage("WindowListener method called: windowOpened.");
    }

    public void windowIconified(WindowEvent e) {
        displayMessage("WindowListener method called: windowIconified.");
    }

    public void windowDeiconified(WindowEvent e) {
        displayMessage("WindowListener method called: windowDeiconified.");
    }

    public void windowActivated(WindowEvent e) {
        displayMessage("WindowListener method called: windowActivated.");
    }

    public void windowDeactivated(WindowEvent e) {
        displayMessage("WindowListener method called: windowDeactivated.");
    }

    public void windowGainedFocus(WindowEvent e) {
        displayMessage("WindowFocusListener method called: windowGainedFocus.");
    }

    public void windowLostFocus(WindowEvent e) {
        displayMessage("WindowFocusListener method called: windowLostFocus.");
    }

    public void windowStateChanged(WindowEvent e) {
        displayStateMessage(
          "WindowStateListener method called: windowStateChanged.", e);
    }

    void displayMessage(String msg) {
        display.append(msg + newline);
        System.out.println(msg);
    }

    void displayStateMessage(String prefix, WindowEvent e) {
        int state = e.getNewState();
        int oldState = e.getOldState();
        String msg = prefix
                   + newline + space
                   + "New state: "
                   + convertStateToString(state)
                   + newline + space
                   + "Old state: "
                   + convertStateToString(oldState);
        displayMessage(msg);
    }

    String convertStateToString(int state) {
        if (state == Frame.NORMAL) {
            return "NORMAL";
        }
        String strState = " ";
        if ((state & Frame.ICONIFIED) != 0) {
            strState += "ICONIFIED";
        }
        //MAXIMIZED_BOTH is a concatenation of two bits, so
        //we need to test for an exact match.
        if ((state & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH) {
            strState += "MAXIMIZED_BOTH";
        } else {
            if ((state & Frame.MAXIMIZED_VERT) != 0) {
                strState += "MAXIMIZED_VERT";
            }
            if ((state & Frame.MAXIMIZED_HORIZ) != 0) {
                strState += "MAXIMIZED_HORIZ";
            }
            if (" ".equals(strState)){
                strState = "UNKNOWN";
            }
        }
        return strState.trim();
    }
}

Window Listener API

窗口监听器 API 由三个窗口监听器interface和WindowEvent类组成。下表列出了它们的方法:

这三个interface中的方法都可以通过WindowAdapter类获得。

WindowListener interface

MethodPurpose
windowOpened(WindowEvent)在首次显示监听窗口之后调用。
windowClosing(WindowEvent)响应于用户请求关闭监听窗口而调用。要实际关闭窗口,侦听器应调用窗口的disposesetVisible(false)方法。
windowClosed(WindowEvent)在监听窗口关闭后调用。
windowIconified(WindowEvent)

windowDeiconified(WindowEvent)
分别在图标化或取消图标化监听窗口之后调用。
windowActivated(WindowEvent)
windowDeactivated(WindowEvent)
分别在激活或禁用监听窗口之后调用。这些方法不会发送到不是框架或对话框的窗口。因此,首选使用windowGainedFocuswindowLostFocus方法来确定窗口何时获得焦点或失去焦点。

WindowFocusListener interface

MethodPurpose
windowGainedFocus(WindowEvent)

windowLostFocus(WindowEvent)
分别在收听窗口获得焦点或失去焦点之后调用。

WindowStateListener interface

MethodPurpose
windowStateChanged(WindowEvent)在通过图标化,去图标化,最大化或返回正常状态更改监听窗口的状态之后立即调用。该状态可通过WindowEvent作为按位掩码使用。在java.awt.Frame中定义的可能值为:


正常。指示未设置任何状态位。
ICONIFIED.
MAXIMIZED_HORIZ.
MAXIMIZED_VERT.
MAXIMIZED_BOTH。String 联MAXIMIZED_HORIZMAXIMIZED_VERT。窗口 管理 器可以支持MAXIMIZED_BOTH,而不支持MAXIMIZED_HORIZMAXIMIZED_VERTjava.awt.Toolkit方法isFrameStateSupported(int)可用于确定窗口 管理 器支持哪些状态。

WindowEvent 类

MethodPurpose
Window getWindow()返回触发事件的窗口。您可以使用此方法代替getSource方法。
Window getOppositeWindow()返回此焦点或激活更改所涉及的另一个窗口。对于WINDOW_ACTIVATEDWINDOW_GAINED_FOCUS事件,这将返回丢失激活或焦点的窗口。对于WINDOW_DEACTIVATEDWINDOW_LOST_FOCUS事件,这将返回获得激活或焦点的窗口。对于 Java 应用程序在不同 VM 或上下文中或没有其他窗口的任何其他类型的WindowEvent,将返回null
int getOldState()

int getNewState()
对于WINDOW_STATE_CHANGED事件,这些方法将窗口的先前或新状态作为按位掩码返回。

使用窗口侦听器的示例

下表列出了使用窗口侦听器的示例。

ExampleWhere DescribedNotes
WindowEventDemoThis section报告在一个窗口上发生的所有窗口事件,以演示触发窗口事件的情况。
SliderDemo如何使用滑块侦听窗口图标化和去图标化事件,以便在不可见窗口时可以停止动画。
InternalFrameEventDemo如何编写内部框架侦听器报告在一个内部框架上发生的所有内部框架事件,以演示触发内部框架事件的情况。内部框架事件类似于窗口事件。
DialogDemoLiterals 组件功能CustomDialog.java使用setDefaultCloseOperation而不是窗口侦听器来确定用户关闭窗口时要采取的操作。
Framework一个演示,允许创建和销毁多个窗口。