I have a standalone Java application that gets data from a database and displays it in a JTable
. When the application starts, the user is prompted for a username/password in a JDialog
. Once the correct credentials are entered, the main JFrame
containing the data is displayed. On the main JFrame
I have a logout button that, when clicked, should close the main JFrame
and redisplay the login JDialog
. Everything is mostly working except I have found that the main JFrame
does not go away when the logout button is clicked. Below is a small working example of my code:
Main.java:
import javax.swing.SwingUtilities;
public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new MainFrame();
}
});
}
}
MainFrame.java:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class MainFrame extends JFrame implements ActionListener {
private JButton button;
private MyDialog dialog;
public MainFrame() {
super("this is the JFrame");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
dialog = new MyDialog(this);
button = new JButton("click me to hide this JFrame and display JDialog");
button.addActionListener(this);
add(button);
pack();
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
setVisible(false); // works when changed to dispose();
dialog.setVisible(true);
}
}
MyDialog.java:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
public class MyDialog extends JDialog implements ActionListener {
private JFrame parentFrame;
private JButton button;
public MyDialog(JFrame parentFrame) {
super(parentFrame, "this is the JDialog", true);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
this.parentFrame = parentFrame;
button = new JButton("click me to hide JDialog and show JFrame");
button.addActionListener(this);
add(button);
pack();
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
setVisible(false);
parentFrame.setVisible(true);
}
}
In MainFrame.java if I change the line that says setVisible(false)
to dispose()
then the JFrame goes away when I click the button. My question is, why does this work with dispose()
and not with setVisible(false)
? Is there a better way for me to organize my code? I am new to Swing so I apologize if this is a basic question. Thank you.
EDITED 2011-10-19 10:26 PDT
Thank you everyone for your help. I changed the JDialog
to have a null parent and now everything works as I wanted.
Later on in a program, if you call setVisible(false) the frame will become invisible, but the software object will still exist and can be made visible again with setVisible(true) . It is easy to forget to include setVisible(true) .
dispose(); causes the JFrame window to be destroyed and cleaned up by the operating system. According to the documentation, this can cause the Java VM to terminate if there are no other Windows available, but this should really just be seen as a side effect rather than the norm.
See the line where you initiate the JDialog:
dialog = new MyDialog(this);
You're setting the same frame as the parent frame that the dialog sits on. You see, a dialog can't appear on its own, it must sit on top of a parent frame.
So in your code, when you write:
setVisible(false); // works when changed to dispose();
dialog.setVisible(true);
In the first line you tell the frame to disappear, then you tell the dialog to appear, which really tells the dialog to appear on its parent frame. Since the parent frame is the same it looks like it stays visible to you. If you remove the second line, I'm sure the frame would disappear. But when you tell the frame to dispose, it disappears entirely because you told it not just to lose visibility, but also remove itself from memory.
Then when you tell the dialog to appear it looks for its JFrame (which has been disposed), re-initializes it and opens up.
The way to solve your problem is to make a separate new JFrame for the JDialog. Then don't use dispose and just use the setVisible command.
-Asaf
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