java 检测何时创建或关闭任何 window

java detect when any window is created or closed

是否可以在创建或关闭应用程序中的任何 window 时收到通知?

目前我正在投票 Window.getWindows(),但我更希望收到通知。

我有:

List<Window> previousWindows = new ArrayList<>();
while (true) {
    List<Window> currentWindows = Arrays.asList(Window.getWindows());

    for (Window window : currentWindows) {
        if (!previousWindows.contains(window)) {
            //window was created
        }
    }

    for (Window window : previousWindows) {
        if (!currentWindows.contains(window)) {
            //window was closed
        }
    }

    previousWindows = currentWindows;
    Thread.sleep(1000);
}

我想要什么:

jvm.addWindowListener(this);

@Override
public void windowWasDisplayed(Window w) {
    //window was created
}

@Override
public void windowWasClosed(Window w) {
    //window was closed
}

您可以注册通过窗口 Toolkit 接收 AWT 事件类型的任何子集的侦听器。从那些你可以 select 和处理 WindowEvent 的 windows 被打开和关闭,像这样:

class WindowMonitor implements AWTEventListener {
    public void eventDispatched(AWTEvent event) {
        switch (event.getID()){
            case WindowEvent.WINDOW_OPENED:
                doSomething();
                break;
            case WindowEvent.WINDOW_CLOSED:
                doSomethingElse();
                break;
        }
    }

    // ...
}

class MyClass {

    // alternative 1
    public void registerListener() {
        Toolkit.getDefaultToolkit().addAWTEventListener(new WindowMonitor(),
                AWTEvent.WINDOW_EVENT_MASK);
    }

    // alternative 2
    public void registerListener(Component component) {
        component.getToolkit().addAWTEventListener(new WindowMonitor(),
                AWTEvent.WINDOW_EVENT_MASK);
    }
}

我推荐备选方案 2,您从中获得 ToolkitComponent 是您应用程序的主要框架(应该只有一个),但备选方案 1 应该适用于如果您必须在不参考任何特定组件的情况下执行此操作(例如,在创建任何组件之前)。

但是请注意,注册 AWTEventListener 需要接受安全检查。

如果您自己创建额外的 windows(我假设是 JFrames),您可以使用 addWindowListener 方法。 WindowAdapter 抽象 class 允许您覆盖您感兴趣的事件的方法:

import java.awt.event.*;
import javax.swing.*;

public class MultipleWindows {
    public static void main(String[] arguments) {
        SwingUtilities.invokeLater(() -> new MultipleWindows().createAndShowGui());
    }

    private void createAndShowGui() {
        JFrame frame = new JFrame("Stack Overflow");
        frame.setBounds(100, 100, 800, 600);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        JPanel panel = new JPanel();
        panel.add(new JLabel("Testing multiple windows..."));
        frame.getContentPane().add(panel);

        WindowAdapter windowAdapter = new WindowAdapter() {
            @Override
            public void windowOpened(WindowEvent windowEvent) {
                System.out.println("Window opened: "
                                   + windowEvent.getWindow().getName());
            }

            @Override
            public void windowClosed(WindowEvent windowEvent) {
                System.out.println("Window closed: "
                                   + windowEvent.getWindow().getName());
            }
        };

        for (int windowIndex = 2; windowIndex < 6; windowIndex++) {
            String title = "Window " + windowIndex;
            JFrame extraFrame = new JFrame(title);
            extraFrame.setName(title);
            extraFrame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
            extraFrame.addWindowListener(windowAdapter);
            extraFrame.setVisible(true);
        }

        frame.setVisible(true);
    }
}