有没有一种方法可以通过代码关闭JDialog,同时仍然会通知窗口事件侦听器? 我已经尝试将visible设置为false和disposing,但似乎都不起作用。
有没有一种方法可以通过代码关闭JDialog,同时仍然会通知窗口事件侦听器? 我已经尝试将visible设置为false和disposing,但似乎都不起作用。关闭窗口(使用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()
调用。如果您需要更普遍地检测隐藏,可以使用HierarchyListener
,但这可能会带来更多麻烦。
window.addHierarchyListener(new HierarchyListener() {
@Override
public void hierarchyChanged(HierarchyEvent e) {
System.out.println("valid: " + window.isValid());
System.out.println("showing: " + window.isShowing());
}
});
注意,当您销毁一个窗口时,您将收到一些 HierarchyEvent
,首先是为隐藏和然后为失效,但当您使用 setVisible()
隐藏它时,它仍然有效,因此您不会收到失效。
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);
}
}
disposeButton
的操作应该调用ClosingDialog.this.dispose()
,而不是再次调用setVisible(false)
。如果你这样做,你会得到一个windowDeactivated
和一个windowClosed
事件--至少我是这样的。windowClosing
事件通常用于通过操作系统控制(例如窗口的红色X)来关闭窗口。 - David Moles向窗口发送窗口关闭事件。请查看关闭应用程序条目中的ExitAction示例。
我想从代码中触发一个windowClosing
事件(就像用户点击X一样),因为我在JDialog中有一个额外的关闭按钮,并且希望当单击X和单击按钮时运行相同的WindowListener(我使用WindowAdapter
实现) 。仅运行dispose()
只会触发windowClosed
,而不是windowClosing
,我希望在窗口关闭之前出现确认消息。我还没有成功通过JDialog的processWindowEvent
方法触发windowClosing
,因为它是受保护的。
以下是我如何使其工作的:
WindowAdapter adapter = (WindowAdapter)jdialog.getWindowListeners()[0];
adapter.windowClosing(new WindowEvent((Window)jdialog, WindowEvent.WINDOW_CLOSING));
未经测试的建议:
您尝试过使用getWindowListeners(),然后迭代每个WindowListener来触发windowClosed()吗?
编辑:上述建议是错误的。为了纪念而保留。
恐怕在我的简单示例中调用dialog.dispose()对我很有效。
windowClosing
事件会得到一个windowClosing
事件和(假设默认关闭操作不是EXIT_ON_CLOSE
)一个windowDeactivated
事件--正如你所说,就像用户点击了X一样。如果你只想关闭窗口并获得一些事件,那似乎并不明显比使用dispose()
得到的事件更有用。它确实具有与X相匹配的优点,因此您可以以同样的方式处理X和程序化的关闭,但是您也可以通过DISPOSE_ON_CLOSE
来获取(反向的)内容。在我看来,这更为简洁,但可能因人而异。 - David Moles