Search code examples
javadialogjvmdispose

Java program not exiting with close button


I have a pretty standard Java Desktop Application in NetBeans. I recently added a jDialog modal as a welcome banner and started having an issue closing the application. If I use the default menu (File > Exit) on the main frame it seems to always close correctly. If I hit the close button on the main window the frame will disappear but the JVM will still be running.

Removing the call to show the dialog box completely fixes the problem, so I am guessing that's where the problem lies. I'm pretty sure the dialog is properly being disposed, as that was my first guess as two why the JVM wouldn't exit.

To check my sanity, instead of calling the my welcome dialog I started calling the default showAboutBox() that is automatically generated by NetBeans when the application was created. Same issue. The dialog works fine when called through the menu (I'm not sure if that's because it's an Action or not) but will cause the JVM not to exit correctly if called directly.

Both dialogs have the setDefaultCloseOperation() set to DISPOSE_ON_CLOSE.

Below is the code snippet for calling the aboutBox (which is the same as my welcome dialog):

@Action
public void showAboutBox() {
    if (aboutBox == null) {
        JFrame mainFrame = MyApp.getApplication().getMainFrame();
        aboutBox = new MyAboutBox(mainFrame);
        aboutBox.setLocationRelativeTo(mainFrame);
    }
    MyApp.getApplication().show(aboutBox);
}

Anyways, I solved the issue myself.

So I guess you can't call a dialog in the constructor...

The fix...

/*
 * MyApp.java
 */

import org.jdesktop.application.Application;
import org.jdesktop.application.SingleFrameApplication;

/**
 * The main class of the application.
 */
public class MyApp extends SingleFrameApplication {

    /**
     * At startup create and show the main frame of the application.
     */
    @Override protected void startup() {
        show(new MyView(this));
        MyView.doThisCodeAfterTheMainFrameIsLoaded();
    }

    /**
     * A convenient static getter for the application instance.
     * @return the instance of MyApp
     */
    public static MyApp getApplication() {
        return Application.getInstance(MyApp.class);
    }

    /**
     * Main method launching the application.
     */
    public static void main(String[] args) {
        launch(MyApp.class, args);
    }

}




/*
 * MyView.java
 */

/**
 * The application's main frame.
 */
public class MyView extends FrameView {

    public MyView(SingleFrameApplication app) {
        super(app);

        initComponents();

        // Don't call a dialog here!
        // showAboutBox();

    }

    public static void doThisCodeAfterTheMainFrameIsLoaded() {

        JFrame mainFrame = MyApp.getApplication().getMainFrame();
        JDialog welcome = new MyWelcome(mainFrame);
        welcome.setLocationRelativeTo(mainFrame);

        MyApp.getApplication().show(welcome);

    }

}

Solution

  • Add the following:

    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    

    See the JFrame documentation:

    Unlike a Frame, a JFrame has some notion of how to respond when the user attempts to close the window. The default behavior is to simply hide the JFrame when the user closes the window. To change the default behavior, you invoke the method setDefaultCloseOperation(int). To make the JFrame behave the same as a Frame instance, use setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE).

    and then look at JFrame.setDefaultCloseOperation