如何关闭JDialog并通知Window事件监听器?

时间:2022-11-20 00:03:53

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并处理,但似乎都没有。

5 个解决方案

#1


47  

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 windowDeactivated to tell you the window's lost focus, but dispose() will then produce windowClosed, while closing from the OS will first produce 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,而从OS关闭将首先产生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()调用。如果你需要更普遍地检测隐藏,你可以使用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()隐藏它时它仍然有效,所以你不会得到失效。

#2


3  

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().

我似乎没有你的问题。当我使用下面的代码时,对于setVisible(false)或dispose()调用windowDeactivated(),并且还调用windowClosed()for 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);
    }
}

#3


1  

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

将windowClosing事件发送到Window。查看Closing an Application条目中的ExitAction示例。

#4


0  

Untested suggestion:

未经测试的建议:

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

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

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()对我来说很好。

#5


0  

I wanted to fire a windowClosing event 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 before the window is closed, for confirmation. I also didn't manage to fire windowClosing via JDialog's method processWindowEvent since it is protected.

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

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.

希望能帮助别人。

#1


47  

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 windowDeactivated to tell you the window's lost focus, but dispose() will then produce windowClosed, while closing from the OS will first produce 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,而从OS关闭将首先产生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()调用。如果你需要更普遍地检测隐藏,你可以使用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()隐藏它时它仍然有效,所以你不会得到失效。

#2


3  

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().

我似乎没有你的问题。当我使用下面的代码时,对于setVisible(false)或dispose()调用windowDeactivated(),并且还调用windowClosed()for 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);
    }
}

#3


1  

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

将windowClosing事件发送到Window。查看Closing an Application条目中的ExitAction示例。

#4


0  

Untested suggestion:

未经测试的建议:

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

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

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()对我来说很好。

#5


0  

I wanted to fire a windowClosing event 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 before the window is closed, for confirmation. I also didn't manage to fire windowClosing via JDialog's method processWindowEvent since it is protected.

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

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.

希望能帮助别人。