wch*_*gin 5 java swing jdialog windowlistener
我有一个扩展的抽象类的应用程序JDialog.该类作为abstract void onClose(),并且在类的构造函数中添加了以下代码:
addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
onClose();
}
}
Run Code Online (Sandbox Code Playgroud)
事件在预期时被触发,但随后发生了一件奇怪的事情.当这个类的一个具体的延长有代码来创建一个新JDialog的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);
}
}
Run Code Online (Sandbox Code Playgroud)
单击"单击我"按钮后,空白JDialog出现并SSCCE.SSCCE().new WindowAdapter() {...}.windowClosed()显示在控制台窗口中.当我关闭空白对话框时,它再次出现,文本再次出现.
另一个非常有趣的事情是当我更改初始化行时
JDialog dialog = new JDialog();
Run Code Online (Sandbox Code Playgroud)
至
JDialog dialog = new JDialog() {
@Override
public synchronized void addWindowListener(WindowListener l) {
super.addWindowListener(l);
System.out
.println("SSCCE.onClose().new JDialog() {...}.addWindowListener()");
}
};
Run Code Online (Sandbox Code Playgroud)
我在控制台中获得以下输出:
单击"单击我"按钮时:
SSCCE.SSCCE().new WindowAdapter() {...}.windowClosed()
SSCCE.onClose().new JDialog() {...}.addWindowListener()
SSCCE.onClose().new JDialog() {...}.addWindowListener()
Run Code Online (Sandbox Code Playgroud)
在第一次关闭对话框时:
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()
Run Code Online (Sandbox Code Playgroud)
在第二次关闭对话框时:
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()
Run Code Online (Sandbox Code Playgroud)
每次关闭对话框时,都会addWindowListener(WindowListener l)被称为额外的时间,即使我没有故意调用它.
我真的不希望在对话框中注册任何 WindowListener s,但我认为简单地覆盖addWindowListener(...)方法而不是调用super.addWindowListener(...)会太过于草率.
我在Mac OS X 10.6.8上运行Java 1.6.0_31,使用Eclipse Indigo(如果重要的话,使用WindowBuilder).
有没有人有任何想法?
谢谢!
每个对话框都依赖于Frame组件.当该帧被销毁时,其依赖对话框也被销毁.
当你使用没有任何参数的JDialog构造函数时,它
创建一个没有标题且没有指定Frame所有者的无模式对话框.共享的隐藏框架将被设置为对话框的所有者.
共享隐藏的帧是SwingUtilities$SharedOwnerFrame,并且在初始化时它将a注册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);
}
Run Code Online (Sandbox Code Playgroud)