Java 如何关闭 JDialog 并通知窗口事件侦听器?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1343542/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 08:27:15  来源:igfitidea点击:

How do I close a JDialog and have the Window Event Listeners be notified?

javaswingjdialog

提问by Jeff Storey

Is there a way to close a JDialog through code such that the Window event listeners will still be notified? I've tried just setting visible to false and disposing, but neither seem to do it.

有没有办法通过代码关闭 JDialog 以便仍会通知 Window 事件侦听器?我试过只将可见设置为 false 和处置,但似乎都没有这样做。

采纳答案by David Moles

Closing a window (with dispose()) and hiding it (with setVisible(false)) are different operations, and produce different events -- and closing it from the operating system is yet another different operation that produces yet a different event.

关闭窗口(使用dispose())和隐藏它(使用setVisible(false))是不同的操作,会产生不同的事件——而从操作系统关闭它是另一种不同的操作,会产生不同的事件。

All three will produce windowDeactivatedto tell you the window's lost focus, but dispose()will then produce windowClosed, while closing from the OS will firstproduce windowClosing. If you want to handle both of these the same way, you can set the window to be disposed when closed:

所有这三个都会产生windowDeactivated告诉您窗口失去焦点,但dispose()随后会产生windowClosed,而从操作系统关闭时将首先产生windowClosing。如果您想以相同的方式处理这两种情况,您可以将窗口设置为关闭时处理:

window.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

In general, setVisible(false)implies that you might want to use the window again, so it doesn't post any window events (apart from windowDeactivated). If you want to detect the hiding of a window, you need to use a ComponentListener;

一般来说,setVisible(false)意味着您可能想要再次使用该窗口,因此它不会发布任何窗口事件(除了windowDeactivated)。如果要检测窗口的隐藏,则需要使用ComponentListener;

window.addComponentListener(new ComponentAdapter() {
  @Override
  public void componentHidden(ComponentEvent e) {
    System.out.println("componentHidden()");
  }
})

Note though that this will pretty much only work for explicit setVisible()calls. If you need to detect hiding more generally, you can use a HierarchyListener, but it's probably more trouble than it's worth.

请注意,这几乎只适用于显式setVisible()调用。如果您需要更普遍地检测隐藏,您可以使用 a HierarchyListener,但这可能比它的价值更麻烦。

  window.addHierarchyListener(new HierarchyListener() {
    @Override
      public void hierarchyChanged(HierarchyEvent e) {
        System.out.println("valid: " + window.isValid());
        System.out.println("showing: " + window.isShowing());
      }
  });

Note that when you dispose a window you'll get a couple of HierarchyEvents, first for hiding and then for invalidation, but when you hide it with setVisible()it's still valid, so you won't get the invalidation.

请注意,当你处理一个窗口时,你会得到几个HierarchyEvents,首先是隐藏,然后是失效,但是当你用setVisible()它隐藏它时,它仍然有效,所以你不会得到失效。

回答by Grundlefleck

Untested suggestion:

未经测试的建议:

Have you tried getWindowListeners() and then iterating around to fire windowClosed() to each of the WindowListeners?

您是否尝试过 getWindowListeners() 然后迭代以将 windowClosed() 触发到每个 WindowListeners ?

EDIT: the above suggestion is wrong. Keeping it for posterity.

编辑:上述建议是错误的。为子孙后代留着。

I'm afraid calling dialog.dispose() works fine for me in my simple example.

在我的简单示例中,恐怕调用 dialog.dispose() 对我来说效果很好。

回答by camickr

Dispatch a windowClosing event to the Window. Check out the ExitAction example from the Closing an Applicationentry.

将 windowClosing 事件分派给 Window。查看关闭应用程序条目中的 ExitAction 示例。

回答by Joseph Gordon

I don't seem to have your problem. When I use the code below windowDeactivated()is called for either setVisible( false )or dispose()and windowClosed()is also called for dispose().

我好像没有你的问题。当我使用下面的代码时,windowDeactivated()setVisible( false )dispose()调用,windowClosed()也为 dispose() 调用。

ClosingDialog.java:

ClosingDialog.java:

public class ClosingDialog extends JDialog {
    public ClosingDialog(Frame owner, String title, boolean modal) {
        super(owner, title, modal);
        JPanel contentPanel = (JPanel) this.getContentPane();

        JButton setVisButton = new JButton("setVisible( false )");
        setVisButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                ClosingDialog.this.setVisible(false);
            }
        });

        JButton disposeButton = new JButton("dispose()");
        disposeButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                ClosingDialog.this.dispose();
            }
        });

        contentPanel.setLayout(new FlowLayout());

        contentPanel.add(setVisButton);
        contentPanel.add(disposeButton);

        this.addWindowListener(new WindowListener() {
            public void windowActivated(WindowEvent e) {
                System.out.println("windowActivated");
            }

            public void windowClosed(WindowEvent e) {
                System.out.println("windowClosed");
            }

            public void windowClosing(WindowEvent e) {
                System.out.println("windowClosing");
            }

            public void windowDeactivated(WindowEvent e) {
                System.out.println("windowDeactivated");
            }

            public void windowDeiconified(WindowEvent e) {
                System.out.println("windowDeiconified");
            }

            public void windowIconified(WindowEvent e) {
                System.out.println("windowIconified");
            }

            public void windowOpened(WindowEvent e) {
                System.out.println("windowOpened");
            }
        });

        this.setSize(300, 300);
    }
}

回答by David Moles

I wanted to fire a windowClosingevent from the code (just as if the user clicked the X), because I have an extra close button in the JDialog and want the same WindowListener (that I implemented using a WindowAdapter) to be run when the X is clicked and when the button is clicked. Running dispose()only fires windowClosed, not windowClosing, and I want a message to appear beforethe window is closed, for confirmation. I also didn't manage to fire windowClosingvia JDialog's method processWindowEventsince it is protected.

我想windowClosing从代码中触发一个事件(就像用户单击 X 一样),因为我在 JDialog 中有一个额外的关闭按钮,并且希望在WindowAdapter单击 X 时运行相同的 WindowListener(我使用 a 实现)当按钮被点击时。dispose()仅运行会触发windowClosed,不会触发,windowClosing我希望在窗口关闭之前显示一条消息以供确认。我也没有设法windowClosing通过 JDialog 的方法触发,processWindowEvent因为它受到保护。

Here is how I got it working though:

这是我如何让它工作的:

WindowAdapter adapter = (WindowAdapter)jdialog.getWindowListeners()[0];
adapter.windowClosing(new WindowEvent((Window)jdialog, WindowEvent.WINDOW_CLOSING));

Hope that helps someone.

希望能帮助某人。