任何人都可以解释为什么以下程序在关闭子窗口时不会终止吗?
我创建了一个简单的应用程序,其中父JFrame
实例化了一个JDialog
的子类。当我将父引用传递给子类以便可以使用父类创建JDialog
时(即:new JDialog(parent);
),从父类添加到它的窗口侦听器会导致程序一旦子窗口关闭,永远不会终止。窗口确实关闭(在可见性方面),但程序本身仍然运行。父项的默认关闭操作设置为JFrame.EXIT_ON_CLOSE
。子项的默认关闭操作设置为JDialog.DISPOSE_ON_CLOSE
。
如果我没有向子类传递父引用,以便在没有父窗口的情况下实例化JDialog
,则示例会在子窗口关闭时终止。例如,如果使用以下内容,程序将终止:ChildWindow prompt = new ChildWindow(null);
父类:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ParentWindow {
private JFrame frame;
private JPanel contentPane = new JPanel(new BorderLayout(0, 0));
private JButton btnNewButton = new JButton("Open Child Window!");
public ParentWindow() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(contentPane);
btnNewButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ChildWindow prompt = new ChildWindow(frame); // or use null for no parent
prompt.getDialog().addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e){
// .. get some information from the child before disposing
System.out.println("Window closed."); // does not terminate when passing frame as parent
frame.dispose();
}
});
}
});
contentPane.add(btnNewButton);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
new ParentWindow();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
儿童班:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ChildWindow {
private JDialog dialog;
private JButton okButton = new JButton("Close");
public ChildWindow(Window parent) {
dialog = new JDialog(parent);
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.getContentPane().setLayout(new BorderLayout());
dialog.getContentPane().add(okButton, BorderLayout.CENTER);
okButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dialog.dispose();
}
});
dialog.pack();
dialog.setVisible(true);
}
public JDialog getDialog() {
return dialog;
}
}
输出:
Window closed.
Window closed.
Window closed.
... (does not terminate)
答案 0 :(得分:3)
使用Windows 7和Java 8测试并且没有问题,当我尝试使用Java 7或Java 6时,它只是继续打印Window Closed.
...
因此,我使用windowClosed
frame.isVisible
方法
btnNewButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ChildWindow prompt = new ChildWindow(frame); // or use null for no parent
prompt.getDialog().addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
// .. get some information from the child before disposing
System.out.println("Window closed."); // does not terminate when passing frame as parent
if (frame.isVisible()) {
frame.dispose();
}
}
});
}
});
让它发挥作用......现在看看我能否找到原因......
我“想”这发生了什么......
okButton
被触发,dialog.dispose
被称为dialog.dispose
正在设置第一个windowClosed
活动WindowListener
已收到windowClosed
事件的通知,该事件处理框架...... WindowListener
他们正在关闭等等......转到3并重复... 这是一个错误,似乎在Java 8中得到修复...因为结束事件已经被推送到事件队列,所以你不会得到StackOverflowException
...
在这种情况下,另一种选择是从触发WindowListener
事件的Window
中删除windowClosed
...
btnNewButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ChildWindow prompt = new ChildWindow(frame); // or use null for no parent
prompt.getDialog().addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
e.getWindow().removeWindowListener(this);
frame.dispose();
}
});
}
});