我看到的差异是(在JDK 1.7上运行):
setVisible(false)
,调用componentHidden
但不windowClosed
(API仅在dispose()
上声明,所以即使它让我感到烦恼也没关系)< / p>
但
dispose()
,调用windowClosed
,但不componentHidden
短期运行的示例代码(MCVE):
public class JDialogTest extends JDialog {
private static final long serialVersionUID = 1L;
public JDialogTest(JFrame owner){
super(owner,ModalityType.APPLICATION_MODAL);
init();
}
private void init() {
this.getContentPane().setLayout(new GridLayout(1,2));
JButton btnVisible = new JButton("Set visible false");
btnVisible.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JDialogTest.this.setVisible(false);
}
});
JButton btnDispose = new JButton("Dispose");
btnDispose.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JDialogTest.this.dispose();
}
});
this.getContentPane().add(btnVisible);
this.getContentPane().add(btnDispose);
this.pack();
}
public static void main(String[] args) {
//A fake frame to test JDialog
JFrame fakeFrame = new JFrame("Fake Frame");
fakeFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fakeFrame.getContentPane().setLayout(new BorderLayout());
JButton btnOpen = new JButton("Open Dialog");
fakeFrame.getContentPane().add(btnOpen,BorderLayout.CENTER);
fakeFrame.pack();
fakeFrame.setLocationRelativeTo(null);
//Generate the test dialog
final JDialogTest dialog = new JDialogTest(fakeFrame);
dialog.addComponentListener(new ComponentAdapter() {
@Override
public void componentShown(ComponentEvent e) {
System.out.println("Component Shown");
}
@Override
public void componentHidden(ComponentEvent e) {
System.out.println("Component Hidden");
}
});
dialog.addWindowListener(new WindowAdapter() {
@Override
public void windowOpened(WindowEvent e) {
System.out.println("Window open");
}
@Override
public void windowClosed(WindowEvent e) {
System.out.println("Window closed");
}
});
dialog.setLocationRelativeTo(null);
btnOpen.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dialog.setVisible(true);
}
});
fakeFrame.setVisible(true);
}
}
注意:该示例包含JDialog
,但我在JFrame
中看到相同的行为,以测试将侦听器简单地附加到fakeFrame
,并添加类似的按钮。 (在MVCE中避免使其 M inimal))。
我考虑过这篇文章:
JDialog setVisible(false) vs dispose()
dispose()
... API文档:
Window.setVisible(boolean b),Window.dispose(),ComponentListener.componentHidden(ComponentEvent e),WindowListener.windowClosed(WindowEvent e)
我为什么要关心:出于好奇,当然还因为我使用按钮关闭窗口(调用dispose()
),界面也可以通过顶部/右边关闭窗口关闭图标和 alt + F4 (调用setVisible(false)
!?)。因此,不能使用上述监听器中的任何一个。只有HierarchyListener
才会捕获它们,这似乎是反直觉的。
编辑:这个问题的范围是“为什么会这样”?目的是什么?“。我期待dispose()
同时调用它们!我在API文档中找不到任何线索,为什么不这样做。
答案 0 :(得分:4)
界面也可以靠近/右窗口关闭图标 alt + F4 (调用setVisible(false)!)
这由默认关闭操作决定。您可以使用setDefaultCloseOperation
进行设置。默认值为HIDE_ON_CLOSE
,这就是您获得componentHidden
调用的原因。如果您将其设置为DISPOSE_ON_CLOSE
,那么您将获得windowClosed
调用。设置为后者将允许您仅注册这些事件类型。
无论如何,隐藏和处理会做不同的事情。处置时释放隐藏的资源不会。此外,隐藏最后一个窗口将不会退出JVM,而处理它将。
事件调度的技术方面,有很多错综复杂的问题。在处理窗口的同时调用其隐藏方法时,事件的调度在操作完成后完成。这意味着EDT可以“事后”调度事件。由于窗口关闭,它不会调度隐藏事件。
答案 1 :(得分:1)
我在为所描述的行为苦苦挣扎时遇到了这个问题。虽然 componentHidden
已被 ComponentEvent(COMPONENT_HIDDEN)
安排到对话框的事件队列,但我的 setVisible(false)
处理程序没有被调用。
我的对话框是模态的,调用者在对话框关闭并从 dispose
返回后显式调用 setVisible(true)
。这可能是对话框事件队列和应用程序事件队列之间的“竞争条件”。因此,我的工作是站在来电者这边:
SwingUtilities.invokeLater(myDialog::dispose);
这应该推迟对话的处理,直到其事件队列耗尽; componentHidden
在此设置中被调用。