Java 窗户关闭会多次起火。这是一个bug还是一个特性?
以下面的代码为例:Java 窗户关闭会多次起火。这是一个bug还是一个特性?,java,swing,dispose,Java,Swing,Dispose,以下面的代码为例: import java.awt.Dialog; import java.awt.event.ActionEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.AbstractAction; import javax.swing.JButton; import javax.swing.JDialog; import javax.swin
import java.awt.Dialog;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
public class WeirdDialogShitTest implements Runnable {
private JFrame frame;
public static void main(String[] args) {
SwingUtilities.invokeLater(new WeirdDialogShitTest());
}
@Override
public void run() {
frame = new JFrame("Test");
frame.add(new JButton(new AbstractAction("Show Dialog") {
@Override
public void actionPerformed(ActionEvent event) {
showDialog();
}
}));
frame.pack();
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.setVisible(true);
}
private void showDialog() {
JDialog dialog = new JDialog(frame, "Dialog", Dialog.ModalityType.DOCUMENT_MODAL);
dialog.add(new JLabel("Content here"));
dialog.pack();
dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
dialog.addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent event) {
JOptionPane.showMessageDialog(frame, "windowClosed fired");
}
});
dialog.setVisible(true);
}
}
我希望在对话框关闭时调用一次windowClosed
实际发生的是,它被调用两次——一次是在对话框关闭时,一次是在包含框架关闭时
当我追踪它看发生了什么时,我发现:
- 在父级上调用
时,它也会处理所有子级。很公平dispose()
- 尽管不再存在,所有子对话框仍保留在子对话框列表中。这在我看来似乎是不可靠的。(它们曾经被移除过吗?)
无条件激发dispose()
无论窗口是否已被释放。对我来说,这似乎也是不可靠的windowClosed
windowClosed
:/
但这可能是预期的行为?应该使用
frame.setDefaultCloseOperation(WindowConstants.EXIT\u ON\u CLOSE)代码>在主框架上。这会解决你的问题。尝试:
public class WeirdDialogShitTest implements Runnable {
private JFrame frame;
public static void main(String[] args) {
SwingUtilities.invokeLater(new WeirdDialogShitTest());
}
@Override
public void run() {
frame = new JFrame("Test");
frame.add(new JButton(new AbstractAction("Show Dialog") {
@Override
public void actionPerformed(ActionEvent event) {
showDialog();
}
}));
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
//Use EXIT_ON_CLOSE here.
}
private void showDialog() {
JDialog dialog = new JDialog(frame, "Dialog", Dialog.ModalityType.DOCUMENT_MODAL);
dialog.add(new JLabel("Content here"));
dialog.pack();
dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
dialog.addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent event) {
JOptionPane.showMessageDialog(frame, "windowClosed fired");
}
});
dialog.setVisible(true);
}
}
“尽管不再存在,但所有子对话框仍保留在子对话框列表中。在我看来,这似乎是不可靠的。(它们是否被删除过?)。dispose的目的是释放窗口及其子组件正在使用的本机资源。这些组件仍然存在于java中,可以自由引用,没有任何例外。根据dispose()
文档,它们可以恢复到与pack()
或show()
@vandale相同的状态。我意识到这一点,但我希望在重新验证之前将其从子帧列表中删除。如果我创建了1000个对话框并处理了所有对话框,那么在应用程序退出之前,是否所有1000个对话框都保留在内存中(我们有多个主窗口,所以在关闭时退出甚至不是一个选项。