Java: How to cancel application exit
Asked Answered
F

2

6

On one of my programs, I want a Dialog to appear when the user attempts to exit the application. The user must then choose to save some state of the program, not to save or to cancel the exit operation.

I wrote this in an attempt to find a solution first and ony then implement it:

import javax.swing.*;
import java.awt.Dimension;
import java.awt.event.*;

class WL implements WindowListener
{
    private boolean statussaved;
    private JFrame tframe;

    WL (JFrame frame)
    {
        statussaved = false;
        tframe = frame;
    }

    @Override public void windowActivated (WindowEvent w) { }
    @Override public void windowClosed (WindowEvent w) { }
    @Override public void windowDeactivated (WindowEvent w) { }
    @Override public void windowDeiconified (WindowEvent w) { }
    @Override public void windowIconified (WindowEvent w) { }
    @Override public void windowOpened (WindowEvent w) { }

    @Override public void windowClosing (WindowEvent w)
    {
        if (statussaved)
        {
            return;
        }

        final JDialog diag = new JDialog (tframe, "Save Progress", true);
        diag.setPreferredSize (new Dimension (500, 100));
        diag.setResizable (false);
        diag.setDefaultCloseOperation (JDialog.DISPOSE_ON_CLOSE);

        JPanel notifypanel = new JPanel ();
        notifypanel.add (new JLabel ("Do you want to save the current status ?"));

        JButton yesbutton = new JButton ("Yes");
        JButton nobutton = new JButton ("No");
        JButton cancelbutton = new JButton ("Cancel");

        yesbutton.addActionListener (new ActionListener ()
        {
            @Override public void actionPerformed (ActionEvent a)
            {
                //SAVE THE STATUS

                System.out.println ("Saving status...");
                statussaved = true;

                diag.dispose ();
                tframe.dispose ();
            }
        });

        nobutton.addActionListener (new ActionListener ()
        {
            @Override public void actionPerformed (ActionEvent a)
            {
                //just exit/close the application

                diag.dispose ();
                tframe.dispose ();
            }
        });

        cancelbutton.addActionListener (new ActionListener ()
        {
            @Override public void actionPerformed (ActionEvent a)
            {
                //DON'T EXIT !!!

                diag.dispose ();
            }
        });

        notifypanel.add (yesbutton);
        notifypanel.add (nobutton);
        notifypanel.add (cancelbutton);

        diag.setContentPane (notifypanel);

        diag.pack ();
        diag.setVisible (true);
    }
}

public class SaveTest
{
    public static void main (String[] args)
    {
        SwingUtilities.invokeLater (new Runnable ()
        {
            @Override public void run ()
            {
                JFrame frame = new JFrame ("Save Test");
                frame.setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE);
                frame.addWindowListener (new WL (frame));

                JLabel lab = new JLabel ("just some information");

                frame.setPreferredSize (new Dimension (400, 300));
                frame.setResizable (false);
                frame.add (lab);
                frame.pack ();
                frame.setVisible (true);
            }
        });
    }
}

It compiles and runs without any change, so you can test it.

The "Yes" and "No" choices work as expected, but I have absolutely no idea what to write in the ActionListener of the "Cancel" button. What I want is, when the user clicks the "Cancel" button, the dialog dissapears, but the main window remains visible (i.e. the program keeps running).

Now, since all this is implemented in the windowClosing method, it's kind of clear that some sort of dispose signal was sent in order to destroy the JFrame. This means that there is probably no way this can be done in the current design. I don't mind reorganizing/redesigning all this to make it work. It's just... I don't know how.

Any ideas ?

Foss answered 12/2, 2012 at 14:37 Comment(0)
C
9

Replace

mainframe.setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE);

with

mainframe.setDefaultCloseOperation (JFrame.DO_NOTHING_ON_CLOSE);

If user cancels closing - do nothing. If agrees - call dispose() manually.

Colugo answered 12/2, 2012 at 14:47 Comment(1)
Thank you, I did just that and it works :) . PS: Actually the change is for mainframe, not diag.Foss
W
6

Have a look at JOptionPane, which handles most of this stuff for you, e.g.

JOptionPane.showConfirmDialog(frame, "please choose one", 
      "information",      
      OptionPane.YES_NO_CANCEL_OPTION, 
      JOptionPane.INFORMATION_MESSAGE);

Your DefaultCloseOperation needs to be DO_NOTHING_ON_CLOSE so that your dialog can handle things - otherwise the window will get disposed before the user can cancel it. Then you manually close the window or exit the application or whatever according to the user's choice.

Woodworth answered 12/2, 2012 at 14:45 Comment(2)
Thanks !!! All I had to do is set the DefaultCloseOperation on mainframe to DO_NOTHING_ON_CLOSE and it worked. Where are you from ? I should send you a few beers :) .Foss
Glad to help. I'm on the other side of Europe, so maybe a bit far for the beers, but thanks anyway ;-)Woodworth

© 2022 - 2024 — McMap. All rights reserved.