Java如何检测窗口的创建和关闭?

6

当应用程序中的任何一个窗口被创建或关闭时,是否有可能收到通知?

目前我正在轮询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
}

你是在使用AWT窗口还是Swing JFrame?如果你正在使用Swing,请不要标记AWT,反之亦然。或者你两个都在用吗? - Frakcool
看起来是两者兼而有之。当我调用Window.getWindows()时,它返回的是awt窗口数组。但是在整个应用程序中,我都在使用JFrames。 - Fidel
1
同时,为了更快地得到更好的帮助,请发布一个 MCVE,这是您在提问时应该已经做过的 :) - Frakcool
1
我建议您不要使用多个JFrames,请阅读The use of multiple JFrames, Good/Bad Practice,也许可以使用CardLayout或模态JDialogs,尽可能避免使用AWT,因为它已经过时了,Swing是为了纠正AWT存在的许多问题而产生的。 - Frakcool
请注意,JFrame是AWT Windows,其他顶级Swing容器JWindowJDialog也是如此。 - John Bollinger
显示剩余4条评论
2个回答

11

您可以通过窗口工具包Toolkit注册接收任何AWT事件类型子集的侦听器。然后,您可以选择并处理窗口打开和关闭的WindowEvent,例如:

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受到安全检查的限制。


非常棒的答案!谢谢John。正是我在寻找的。 - Fidel

0
如果您自己创建了额外的窗口(我假设是JFrame),则可以使用addWindowListener方法。 WindowAdapter抽象类允许您覆盖您感兴趣的事件的方法:
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);
    }
}

1
我很确定在Window上注册WindowListener只会导致该监听器接收该Window触发的WindowEvent,而不是由任何其他Window触发的WindowEvent。 - John Bollinger
1
@JohnBollinger - 是的,你说得完全正确。这种方法是针对你直接创建的窗口感兴趣的事件使用案例而设计的。如果需要的话,你还可以调用Window.getWindows方法来为其他窗口注册窗口监听器。 - Freek de Bruijn
@Freek de Bruijn,请阅读我在这里的答案,这只是为您准备的,请确保WindowListener是正确的方法。 - mKorbel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接