The difference I see is (running on JDK 1.7):
setVisible(false)
, invokescomponentHidden
but notwindowClosed
(The API states only ondispose()
so it's OK even if it irritates me)
but
dispose()
, invokeswindowClosed
but notcomponentHidden
Short running example code (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);
}
}
NOTE: The example features a JDialog
, but I see same behavior in JFrame
, to test simple attach the listeners to the fakeFrame
, and add similar buttons. (avoided in MVCE to keep it Minimal)).
I have considered this post:
JDialog setVisible(false) vs dispose()
dispose()
...API DOCUMENTATION:
Window.setVisible(boolean b), Window.dispose(), ComponentListener.componentHidden(ComponentEvent e), WindowListener.windowClosed(WindowEvent e)
Why do I care: Naturally out of curiosity, but also since I use buttons to close the window (invoking dispose()
) and the interface can also be closed by the top/right window close icon and alt+F4 (invoking setVisible(false)
!?). Hence no one of the above listener can be used. Only the HierarchyListener
will catch them both and this seems counter intuitive.
EDIT: The question is scoped as "why is it like this"? What is the purpose?". I was expecting dispose()
to invoke both! I can't find any clues in the API documentation for why not.
setVisible(false) doesn't free the resources used by the JFrame--it just takes it off the screen.
setVisible(true) is a blocking operation and blocks until dialog is closed. So one dialog pops up and app blocks on setVisible(true) when you close it, another serVisible(true) is invoked and so on.
We set the size and visibility of the frame by method setSize() and setVisible(). The layout is set by the method setLayout() method.
the interface can also be close by top/right window close icon alt+F4 (invoking setVisible(false)!?)
This is determined by the default close operation. You can set it with setDefaultCloseOperation
. The default is HIDE_ON_CLOSE
, which is why you get a componentHidden
invocation. If you set it to DISPOSE_ON_CLOSE
then you will get a windowClosed
invocation instead. Setting to the latter will allow you to only register for those event types.
Regardless, hiding and disposing do different things. Disposing releases the resources used while hiding doesn't. Also, hiding the last window will not exit the JVM while disposing it will.
As for the technical side of event dispatching, there are a lot of intricacies. While disposing the window does call its hiding method, the dispatching of events is done after operations are done. This means that the EDT can dispatch events "after the fact". Since the window is closed, it does not dispatch the hiding event.
I came accross this question while struggling with the behaviour described. My handler for componentHidden
were not called although a ComponentEvent(COMPONENT_HIDDEN)
was scheduled to the dialog's event queue by setVisible(false)
.
My dialog is modal and the caller invokes dispose
explicitely after the dialog is closed and returns from setVisible(true)
. Probably this is a "race condition" between the dialog's event queue und the application's event queue. My work around therefore is on the caller's side:
SwingUtilities.invokeLater(myDialog::dispose);
This should postpone the disposal of the dialog until its event queue is exhausted; componentHidden
is called in this setting.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With