当前位置: 首页 > 知识库问答 >
问题:

来自父类的非终止窗口侦听器

晏经武
2023-03-14

任何人都可以解释为什么以下程序在关闭子窗口时不会终止?

我已经创建了一个简单的应用程序,它具有一个父<code>JFrame</code>,它使用<code>JDialog</code>实例化一个子类。当我将父引用传递到子类中,以便可以使用父类创建JDialog时(即:newJDialog(parent)),从父类添加到它的窗口监听器会导致程序在子窗口关闭后永远不会终止。窗口确实关闭(在可见性方面),但程序本身仍在运行。父级的默认关闭操作设置为JFrame.EXIT_ON_close。子级的默认关闭操作设置为JDialog.DISPOSE_ON_close

如果我不向子类传递父引用,以便在没有父窗口的情况下实例化JDialog,则该示例会在子窗口关闭时终止。例如,如果使用以下内容,程序就会终止:ChildWindow提示符=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)

共有1个答案

咸正平
2023-03-14

使用Windows 7和Java 8进行了测试,没有问题,当我尝试Java 7或Java 6时,它只是继续打印<code>窗口关闭。</code>。。。

因此,我使用的测试更新了窗口已关闭方法。

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();
                }
            }
        });
    }
});

并让它工作...现在看看我是否可以找出原因...

我“认为”发生的事情是这样的...

    < li> 确定按钮被触发,调用< code>dialog.dispose < li> dialog.dispose正在设置第一个< code>windowClosed事件 < li >向< code>WindowListener通知< code>windowClosed事件,该事件正在处理该帧... < li >框架试图关闭其子窗口,这导致对话框再次通知< code>WindowListener它们正在关闭,等等...转到3并重复...

这是一个错误,在 Java 8 中似乎已修复...因为关闭事件被推送到事件队列中,所以你不会得到堆栈溢出异常...

在这种情况下,另一个选项是从触发windowClosed事件的Window中删除WindowListener

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();
            }
        });
    }
});
 类似资料:
  • 我正在处理JButton事件。我有一个JPanel类,我们叫Panel1,包含一个公共的JButton,我们叫它Button1。单击此按钮时: 但我有兴趣: 有什么建议吗?

  • 问题内容: 我正在使用https://github.com/gin-gonic/gin编写http服务,但是当我部署它时,它会继续部署在tcp6上(根据netstat) 问题答案: 文档说明 运行将路由器连接到http.Server并开始侦听和处理HTTP请求。这是http.ListenAndServe(addr,router)的快捷方式 您可以使用与软件包相同的方式直接启动服务器

  • 有没有办法防止事件链中的一些听众为事件开火,但允许链上的其他人开火? 比如我有这个结构 假设我已经将单击事件监听器连接到body、div#1和div#2。是否有可能在div#2事件监听器上阻止事件进入div#1或介于两者之间的任何其他监听器,并允许事件在body元素上触发? 我这样说是因为我使用谷歌地图和emberjs构建了一系列可以在地图上显示的交互式信息框。问题是ember将事件侦听器附加到b

  • 我已经用重新启动了influxdb,但是没有任何帮助。 我错过了什么? 更新7.11.2016 21:59 更新13.4.2020问题已修复。 这是一个老问题,我不记得我到底是如何解决这个问题的,但我做到了。如果我没记错的话,问题是流入没有加载正确的配置文件,这是我自己当时的愚蠢。可悲的是,我不记得为什么会发生这种事,但我记得这是我自己做的。记住总是正确地阅读文档,并谷歌出它的sht。

  • 问题内容: 我正在根据其在视口中的位置为几个React.js组件设置动画。如果组件中视,动画不透明度为1,如果不是在视口中,有生其不透明度为0。我使用的和属性,以确定该组件是视域之内。 ComponentA显示了我遵循的其他B,C和D组件的模式。他们每个人都在监听滚动事件。 这是每个组件都必须向事件添加事件侦听器的“反应”方式吗?同一窗口上有多个滚动事件侦听器? 还是通过在所有者组件处将滚动事件侦