我有一个具有扩展JDialog的抽象类的应用程序。类作为一个abstract void onClose(),并且在类的构造函数中添加以下代码:
addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
onClose();
}
}事件是在预期时触发的,但随后发生了一件奇怪的事情。当这个类的一个具体扩展有代码在onClose()方法中创建一个新的onClose(),并且这个JDialog的defaultCloseOperation是JDialog.DISPOSE_ON_CLOSE时,这个事件就会不断地被触发,直到我强制退出操作。
我已经将代码隔离到以下SSCCE:
// package removed
// imports removed
public class SSCCE extends JDialog {
public static void main(String[] args) {
SSCCE s = new SSCCE();
s.pack();
s.setVisible(true);
}
public SSCCE() {
setLayout(new GridLayout(1, 0, 0, 0));
JButton btn = new JButton("click me");
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
dispose();
}
});
addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
System.out
.println("SSCCE.SSCCE().new WindowAdapter() {...}.windowClosed()");
onClose();
}
});
add(btn);
}
public void onClose() {
JDialog dialog = new JDialog();
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
}
}单击“单击我”按钮后,空白的JDialog出现,SSCCE.SSCCE().new WindowAdapter() {...}.windowClosed()出现在控制台窗口中。当我关闭空白对话框时,它再次出现,文本再次出现。
另一件非常有趣的事情是,当我将初始化行更改为
JDialog dialog = new JDialog();至
JDialog dialog = new JDialog() {
@Override
public synchronized void addWindowListener(WindowListener l) {
super.addWindowListener(l);
System.out
.println("SSCCE.onClose().new JDialog() {...}.addWindowListener()");
}
};我在控制台中得到以下输出:
单击“单击我”按钮时:
SSCCE.SSCCE().new WindowAdapter() {...}.windowClosed()
SSCCE.onClose().new JDialog() {...}.addWindowListener()
SSCCE.onClose().new JDialog() {...}.addWindowListener()在对话框的第一次结束时:
SSCCE.SSCCE().new WindowAdapter() {...}.windowClosed()
SSCCE.onClose().new JDialog() {...}.addWindowListener()
SSCCE.onClose().new JDialog() {...}.addWindowListener()
SSCCE.onClose().new JDialog() {...}.addWindowListener()
SSCCE.onClose().new JDialog() {...}.addWindowListener()在对话框的第二次结束时:
SSCCE.SSCCE().new WindowAdapter() {...}.windowClosed()
SSCCE.onClose().new JDialog() {...}.addWindowListener()
SSCCE.onClose().new JDialog() {...}.addWindowListener()
SSCCE.onClose().new JDialog() {...}.addWindowListener()
SSCCE.onClose().new JDialog() {...}.addWindowListener()
SSCCE.onClose().new JDialog() {...}.addWindowListener()每次我关闭对话框时,都会调用addWindowListener(WindowListener l)额外的时间,即使它不是我有意调用的。
我真的不希望在对话框中注册任何WindowListener,但我认为简单地覆盖addWindowListener(...)方法而不调用super.addWindowListener(...)太草率了。
我使用Eclipse在MacOSX10.6.8上运行1.6.0_31 (如果有关系的话,可以使用WindowBuilder )。
有人有什么想法吗?
谢谢!
发布于 2012-04-20 00:05:33
根据Java对话框教程,
每个对话框都依赖于框架组件。当该帧被破坏时,它的依赖对话框也是如此。
当您使用没有任何参数的JDialog构造函数时,
创建一个没有标题且没有指定的框架所有者的非模态对话框。一个共享的隐藏帧将被设置为对话框的所有者。
共享隐藏帧是SwingUtilities$SharedOwnerFrame,初始化时它向所有拥有的窗口注册一个WindowListener。
当您关闭对话框时,将调用SharedOwnerFrame的windowClosed方法,该方法检查它所拥有的所有窗口(此时是原始的SSCCE对话框和新的窗口),它会发现没有一个是可见的,因此它会自行处理。这会影响处理它所拥有的所有对话框,该对话框会向每个对话框发送一个窗口关闭事件。这将在侦听器中调用windowClosed,打开一个新对话框。然后再转一遍:-)。关于您的最后一个注释,您每次都会得到额外的日志行,因为每个SharedOwnerFrame拥有一个对话框。
如果使SSCCE对话框拥有新的(通过将this传递给其构造函数),那么您就不会以共享所有权结束,它工作得很好:
public void onClose() {
JDialog dialog = new JDialog(this);
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
}发布于 2012-04-19 21:42:21
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
public class SSCCE extends JDialog {
public static void main(String[] args) {
SSCCE s = new SSCCE();
s.pack();
s.setVisible(true);
}
private WindowAdapter wa = new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
System.out
.println("SSCCE.SSCCE().new WindowAdapter() {...}.windowClosed()");
onClose();
}
};
public SSCCE() {
setLayout(new GridLayout(1, 0, 0, 0));
JButton btn = new JButton("click me");
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
dispose();
}
});
addWindowListener(
wa);
add(btn);
}
public void onClose() {
removeWindowListener(wa);
JDialog dialog = new JDialog();
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
}
}https://stackoverflow.com/questions/10237047
复制相似问题