【发布时间】:2015-09-18 15:48:44
【问题描述】:
我目前正在处理一个具有始终存在的主要JFrame 的工作应用程序。我目前有一个孩子JDialog,它会在按下按钮时出现。此框架有一个JMenu,其中包含一个“退出显示”项目。我的任务是确保当按下退出显示选项时这个孩子JDialog 消失。注销时,通过以下方式将主显示设置为不可见:
mainFrame.setVisible(false);
子JDialog有默认关闭操作:
DISPONSE_ON_CLOSE
当用户重新登录时,首先要做的是:
mainFrame.setVisible(true);
发生这种情况时,子对话框会重新显示。查看JDialog Javadoc,这似乎是预期的行为。但是我还没有找到打破父母/孩子关系或完全摧毁孩子JDialog的方法。似乎JDialog 将一直保留到 GC 为止,这可能不会及时发生。
这是一个模拟我看到的行为的示例程序:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JToggleButton;
import javax.swing.SwingUtilities;
public class WindowTest {
public static void createAndShowGUI() {
JFrame aFrame = new JFrame("LAUNCHER");
final JFrame aParent = new JFrame("PARENT");
final JDialog aChild = new JDialog(aParent);
aParent.setSize(200,200);
final JToggleButton showParentButton = new JToggleButton("HIDE");
showParentButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
showParentButton.setText(!showParentButton.isSelected() ? "SHOW": "HIDE");
aParent.setVisible(!showParentButton.isSelected());
}
});
aChild.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
aChild.setSize(200,200);
aParent.addComponentListener(new ComponentAdapter() {
public void componentHidden(ComponentEvent e) {
aChild.dispose();
aChild.setVisible(false);
}
});
aFrame.setContentPane(showParentButton);
aFrame.pack();
aFrame.setVisible(true);
aParent.setVisible(true);
aChild.setVisible(true);
}
public static void main(String [] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
createAndShowGUI();
}
});
}
}
当父级被隐藏时,子级被释放。当父母出现时,孩子会重新出现。真正奇怪的是,当我在孩子身上按下 X 时:当父母被隐藏然后再次显示时,孩子并没有重新出现。
我看到的唯一区别是单击 X 也会触发 WindowClosing 事件。我在上面的componentHidden方法中尝试了dispatch:
//Added into the constructor
//add to the imports: import java.awt.event.WindowEvent;
aParent.addComponentListener(new ComponentAdapter() {
public void componentHidden(ComponentEvent e) {
aChild.dispose();
aChild.setVisible(false);
WindowEvent closingEvent =
new WindowEvent(aChild, WindowEvent.WINDOW_CLOSING);
aChild.dispatchEvent(closingEvent);
}
});
这并没有解决问题。
目前看来我唯一的选择是将孩子的类型更改为JFrame。我只是想知道是否有适当的方式处置孩子JDialog。
我目前在 Redhat Enterprise Linux Server 6.4 版上运行 Java 版本:1.7.0_76 64 位。
【问题讨论】:
-
默认情况下是不可能的 - dispose == setVisible(false),重用 JDialog 进行花药操作,使用 HIDE_ON_CLOSE
-
我无法重复使用该对话框。 (需求、糟糕的设计、现有代码等)
-
@mKorbel 该问题的答案似乎表明 Dialog 实际上有资格进行垃圾收集,一旦它被处置。与往常一样,不能保证没有引用它的对象会立即被垃圾收集。
-
所以基本上这是不可能的。您无法从父框架中删除子框架似乎很奇怪。
-
Here is a sample program that simulates the behavior I'm seeing:- 1) 变量名不应以大写字符开头。 2)代码应该是完整的,所以我们可以复制/粘贴/编译。它没有编译,所以我无法测试它。