gpt4 book ai didi

java - 来自父类的非终止窗口监听器

转载 作者:行者123 更新时间:2023-11-29 05:22:28 24 4
gpt4 key购买 nike

谁能解释一下为什么关闭子窗口时下面的程序没有终止?

我创建了一个简单的应用程序,它有一个父 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)

最佳答案

使用 Windows 7 和 Java 8 测试没有问题,当我尝试 Java 7 或 Java 6 时,它只是继续打印 Window Closed....

因此,我使用 frame.isVisible 测试更新了 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) {
// .. 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();
}
}
});
}
});

让它开始工作......现在看看我是否能找出原因......

我“认为”这是发生了什么......

  1. okButton 被触发,dialog.dispose 被调用
  2. dialog.dispose 正在设置第一个 windowClosed 事件
  3. WindowListener 收到有关 windowClosed 事件的通知,该事件正在处理框架...
  4. 框架正试图关闭它的子窗口,这导致对话框再次通知 WindowListener 它们正在关闭等等...转到 3 并重复...

这是一个错误,似乎已在 Java 8 中修复...因为关闭事件被推送到事件队列中,您不会得到 StackOverflowException...

在这种情况下,另一种选择是从触发 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();
}
});
}
});

关于java - 来自父类的非终止窗口监听器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24132413/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com