Swing Application Shutdown

After discussing the startup in the last post I continue on the shutdown of a Java application. Typically when the application frame (or window) closes the user is asked if he really wants to exit. If he commits this the application exits while closing the application. In the other case the application might restart or do nothing. How can this be handled with Java Swing?

A common way of shutdown implementation is to add an implementation of WindowListener to the application frame and react on the events. The listener already has a callback windowClosing(WindowEvent) which is called before the window closes. Here the application might ask the user if he really wants to exit or just clicked the wrong button ;-). In most cases if the user commits a common implementation is to invoke System.exit(0) because this terminates the JVM but the JFrame class provides a more convinient approach. Simply set the default closing operation to JFrame.EXIT_ON_CLOSE will do the same job. If the application requires a callback that the application frame is really closed simply set the closing operation to JFrame.DISPOSE_ON_CLOSE and implement the listeners windowClosed(WindowEvent) method. You even don’t need to invoke System.exit(int) because the EDT exits when no window is active. Which means if the application frame is the only window it also exits the application.

Application Shutdown

This image shows the event invocations when a window is closed. First the user closes the window by pressing the red icon in the top right corner. This causes the EDT to dispatch a window event to the application frame. The event has the type WindowEvent.WINDOW_CLOSING. The application has registered a WindowListener that invokes shutdown in the EDT. In the shutdown method the application asks the user if he really wants to exit. If he aborts the application sets the default close operation to JFrame.DO_NOTHING_ON_CLOSE which continues the application and keeps the frame open. If the user commits the application sets the default close operation to DISPOSE_ON_CLOSE which causes the application frame to be disposed. This again causes the EDT to dispatch a new WindowEvent with the type WindowEvent.CLOSED. Now the application can do some magic in the EDT after the window is closed. If no window exists the EDT exits and the JVM terminates. If the application sets the default close operation to JFrame.EXIT_ON_CLOSE the application will terminate immediately after the windowClosing method is executed (just look at the code of JFrame’s processWindowEvent method).


2 Gedanken zu “Swing Application Shutdown

  1. Since I hardly ever work with Swing, this was a nice to-the-point introduction, thank you! I suppose a little code-example would’ve been appreciated, but mucking around a bit in my IDE was enough to work it out 🙂

  2. The following code contains an example that tests the closing behavior and uses Log4J to output log messages at interesting locations.

    /*
    * Copyright 2009 Daniel Rohe
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
    *
    * http://www.apache.org/licenses/LICENSE-2.0
    *
    * Unless required by applicable law or agreed to in writing, software
    * distributed under the License is distributed on an "AS IS" BASIS,
    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    * See the License for the specific language governing permissions and
    * limitations under the License.
    */
    package net.sf.daro.core;

    import java.awt.Dimension;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;

    import javax.swing.JFrame;
    import javax.swing.JOptionPane;
    import javax.swing.SwingUtilities;

    import org.apache.log4j.Logger;

    /**
    * @author Daniel
    */
    public class FrameTester {

    /**
    * logging support
    */
    private static Logger log = Logger.getLogger(FrameTester.class);

    private JFrame applicationFrame;

    public FrameTester() {
    super();
    }

    public void startup() {
    log.debug("startup application");

    applicationFrame = new JFrame("FrameTester");
    applicationFrame.setMinimumSize(new Dimension(320, 280));
    applicationFrame.addWindowListener(new ApplicationFrameListener());

    applicationFrame.setVisible(true);
    }

    public void shutdown() {
    log.debug("shutdown application");

    int option = JOptionPane.showConfirmDialog(applicationFrame
    .getRootPane(), "Do you want to exit the application?",
    "Exit Application", JOptionPane.YES_NO_OPTION);
    if (option == JOptionPane.YES_OPTION) {
    // if user commits closing the application simply exits without
    // disposing the frame
    applicationFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    } else if (option == JOptionPane.NO_OPTION) {
    // in case user cancels the closing the application disposes the
    // frame and calls windowClosed() which starts the frame again
    applicationFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    } else {
    // if he closes the window we do nothing
    applicationFrame
    .setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
    }

    }

    private class ApplicationFrameListener extends WindowAdapter {

    /**
    * {@inheritDoc}
    *
    * @see java.awt.event.WindowAdapter#windowOpened(java.awt.event.WindowEvent)
    */
    @Override
    public void windowOpened(WindowEvent e) {
    log.debug("application frame - window opened");
    }

    /**
    * {@inheritDoc}
    *
    * @see WindowAdapter#windowClosing(WindowEvent)
    */
    @Override
    public void windowClosing(WindowEvent e) {
    log.debug("application frame - window closing");

    shutdown();
    }

    /**
    * {@inheritDoc}
    *
    * @see WindowAdapter#windowClosed(WindowEvent)
    */
    @Override
    public void windowClosed(WindowEvent e) {
    log.debug("application frame - window closed");

    startup();
    }

    }

    public static void main(String[] args) throws Exception {
    final Class applicationClass = FrameTester.class;
    if (SwingUtilities.isEventDispatchThread()) {
    FrameTester application = applicationClass.newInstance();
    application.startup();
    } else {
    SwingUtilities.invokeAndWait(new Runnable() {
    @Override
    public void run() {
    try {
    FrameTester application = applicationClass
    .newInstance();
    application.startup();
    } catch (Exception e) {
    throw new RuntimeException(e);
    }
    }
    });
    }
    }
    }

Hinterlasse eine Antwort zu danielrohe Antwort abbrechen