34

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

4

5 回答 5

49

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

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

window.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

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

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

请注意,这几乎只适用于显式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());
      }
  });

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

于 2009-08-31T08:48:59.583 回答
3

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

关闭对话框.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);
    }
}
于 2009-08-27T21:17:13.873 回答
1

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

于 2009-08-27T20:37:13.283 回答
0

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

这是我如何让它工作的:

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

希望对某人有所帮助。

于 2013-06-01T18:32:01.863 回答
0

未经测试的建议:

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

编辑:上述建议是错误的。留给后人。

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

于 2009-08-27T20:28:23.270 回答