首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >“`WindowListener`”活动,永久触发

“`WindowListener`”活动,永久触发
EN

Stack Overflow用户
提问于 2012-04-19 21:26:35
回答 2查看 830关注 0票数 5

我有一个具有扩展JDialog的抽象类的应用程序。类作为一个abstract void onClose(),并且在类的构造函数中添加以下代码:

代码语言:javascript
复制
addWindowListener(new WindowAdapter() {
    @Override
    public void windowClosed(WindowEvent e) {
        onClose();
    }
}

事件是在预期时触发的,但随后发生了一件奇怪的事情。当这个类的一个具体扩展有代码在onClose()方法中创建一个新的onClose(),并且这个JDialogdefaultCloseOperationJDialog.DISPOSE_ON_CLOSE时,这个事件就会不断地被触发,直到我强制退出操作。

我已经将代码隔离到以下SSCCE:

代码语言:javascript
复制
// 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()出现在控制台窗口中。当我关闭空白对话框时,它再次出现,文本再次出现。

另一件非常有趣的事情是,当我将初始化行更改为

代码语言:javascript
复制
JDialog dialog = new JDialog();

代码语言:javascript
复制
JDialog dialog = new JDialog() {
        @Override
        public synchronized void addWindowListener(WindowListener l) {
            super.addWindowListener(l);
            System.out
                    .println("SSCCE.onClose().new JDialog() {...}.addWindowListener()");
        }
    };

我在控制台中得到以下输出:

单击“单击我”按钮时:

代码语言:javascript
复制
SSCCE.SSCCE().new WindowAdapter() {...}.windowClosed()
SSCCE.onClose().new JDialog() {...}.addWindowListener()
SSCCE.onClose().new JDialog() {...}.addWindowListener()

在对话框的第一次结束时:

代码语言:javascript
复制
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()

在对话框的第二次结束时:

代码语言:javascript
复制
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 )。

有人有什么想法吗?

谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-04-20 00:05:33

根据Java对话框教程

每个对话框都依赖于框架组件。当该帧被破坏时,它的依赖对话框也是如此。

当您使用没有任何参数的JDialog构造函数时,

创建一个没有标题且没有指定的框架所有者的非模态对话框。一个共享的隐藏帧将被设置为对话框的所有者。

共享隐藏帧是SwingUtilities$SharedOwnerFrame,初始化时它向所有拥有的窗口注册一个WindowListener

当您关闭对话框时,将调用SharedOwnerFramewindowClosed方法,该方法检查它所拥有的所有窗口(此时是原始的SSCCE对话框和新的窗口),它会发现没有一个是可见的,因此它会自行处理。这会影响处理它所拥有的所有对话框,该对话框会向每个对话框发送一个窗口关闭事件。这将在侦听器中调用windowClosed,打开一个新对话框。然后再转一遍:-)。关于您的最后一个注释,您每次都会得到额外的日志行,因为每个SharedOwnerFrame拥有一个对话框。

如果使SSCCE对话框拥有新的(通过将this传递给其构造函数),那么您就不会以共享所有权结束,它工作得很好:

代码语言:javascript
复制
 public void onClose() {
     JDialog dialog = new JDialog(this);
     dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
     dialog.setVisible(true);
 }
票数 7
EN

Stack Overflow用户

发布于 2012-04-19 21:42:21

代码语言:javascript
复制
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);

    }

}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10237047

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档