Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Swing dispose() vs. setVisible(false)

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.

like image 311
user1002119 Avatar asked Oct 18 '11 22:10

user1002119


People also ask

What is setVisible false in Java?

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) .

What does dispose do in Java Swing?

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.


1 Answers

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

like image 116
Asaf Avatar answered Oct 09 '22 10:10

Asaf