How to override windowsClosing event in JFrame

20,866

Solution 1

Adding a New Code with no WindowListener part as explained by @JBNizet, the very right thing. The default behaviour just hides the window, nothing is lost, you simply have to bring it back, every value inside it will remain as is, below is the sample program for further help :

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

public class TwoFrames
{
    private SecondFrame secondFrame;
    private int count = 0;

    private void createAndDisplayGUI()
    {
        JFrame frame = new JFrame("JFRAME 1");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationByPlatform(true);

        secondFrame = new SecondFrame();
        secondFrame.createAndDisplayGUI();
        secondFrame.tfield.setText("I will be same everytime.");

        JPanel contentPane = new JPanel();  
        JButton showButton = new JButton("SHOW JFRAME 2");
        showButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ae)
            {
                secondFrame.tfield.setText(secondFrame.tfield.getText() + count);
                count++;
                if (!(secondFrame.isShowing()))
                    secondFrame.setVisible(true);
            }
        });

        frame.add(contentPane, BorderLayout.CENTER);
        frame.add(showButton, BorderLayout.PAGE_END);
        frame.setSize(200, 200);
        frame.setVisible(true);
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new TwoFrames().createAndDisplayGUI();
            }
        });
    }
}

class SecondFrame extends JFrame
{
    private WindowAdapter windowAdapter;
    public JTextField tfield;

    public void createAndDisplayGUI()
    {
        setLocationByPlatform(true);

        JPanel contentPane = new JPanel();

         tfield = new JTextField(10);

        addWindowListener(windowAdapter);
        contentPane.add(tfield);

        getContentPane().add(contentPane);
        setSize(300, 300);      
    }
}

Is this what you want, try this code :

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

public class TwoFrames
{
    private SecondFrame secondFrame;

    private void createAndDisplayGUI()
    {
        JFrame frame = new JFrame("JFRAME 1");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationByPlatform(true);

        secondFrame = new SecondFrame();
        secondFrame.createAndDisplayGUI();
        secondFrame.tfield.setText("I will be same everytime.");

        JPanel contentPane = new JPanel();  
        JButton showButton = new JButton("SHOW JFRAME 2");
        showButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ae)
            {
                if (!(secondFrame.isShowing()))
                    secondFrame.setVisible(true);
            }
        });

        frame.add(contentPane, BorderLayout.CENTER);
        frame.add(showButton, BorderLayout.PAGE_END);
        frame.setSize(200, 200);
        frame.setVisible(true);
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new TwoFrames().createAndDisplayGUI();
            }
        });
    }
}

class SecondFrame extends JFrame
{
    private WindowAdapter windowAdapter;
    public JTextField tfield;

    public void createAndDisplayGUI()
    {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationByPlatform(true);

        JPanel contentPane = new JPanel();

         tfield = new JTextField(10);

        windowAdapter = new WindowAdapter()
        {
            public void windowClosing(WindowEvent we)
            {
                setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
            }
        };

        addWindowListener(windowAdapter);
        contentPane.add(tfield);

        getContentPane().add(contentPane);
        setSize(300, 300);      
    }
}

Solution 2

don't create a new JFrame, for new container use JDialog, if you want to hide the JFrame then better would be override proper e.g DefaultCloseOperations(JFrame.HIDE_ON_CLOSE), method JFrame.EXIT_ON_CLOSE teminating current JVM instance simlair as calll for System.exit(int)

EDIT

but it still continue to terminate my entire app. 

1) then there must be another issue, your code maybe call another JFrame or formWindowClosing <> WindowClosing, use implemented method from API

public void windowClosing(WindowEvent e) {

2) I'b preferred DefaultCloseOperations(JFrame.HIDE_ON_CLOSE),

3) use JDialog instead of JFrame

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

public class ClosingFrame extends JFrame {

    private JMenuBar MenuBar = new JMenuBar();
    private static JFrame frame = new JFrame();
    private static JFrame frame1 = new JFrame("DefaultCloseOperation(JFrame.HIDE_ON_CLOSE)");
    private static final long serialVersionUID = 1L;
    private JMenu File = new JMenu("File");
    private JMenuItem Exit = new JMenuItem("Exit");

    public ClosingFrame() {
        File.add(Exit);
        MenuBar.add(File);
        Exit.addActionListener(new ExitListener());
        WindowListener exitListener = new WindowAdapter() {

            @Override
            public void windowClosing(WindowEvent e) {
                frame.setVisible(false);
                /*int confirm = JOptionPane.showOptionDialog(frame,
                "Are You Sure to Close this Application?",
                "Exit Confirmation", JOptionPane.YES_NO_OPTION,
                JOptionPane.QUESTION_MESSAGE, null, null, null);
                if (confirm == JOptionPane.YES_OPTION) {
                System.exit(1);
                }*/
            }
        };
        JButton btn = new JButton("Show second JFrame");
        btn.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                frame1.setVisible(true);
            }
        });
        frame.add(btn, BorderLayout.SOUTH);
        frame.addWindowListener(exitListener);
        frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
        frame.setJMenuBar(MenuBar);
        frame.setPreferredSize(new Dimension(400, 300));
        frame.setLocation(100, 100);
        frame.pack();
        frame.setVisible(true);
    }

    private class ExitListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            int confirm = JOptionPane.showOptionDialog(frame,
                    "Are You Sure to Close this Application?",
                    "Exit Confirmation", JOptionPane.YES_NO_OPTION,
                    JOptionPane.QUESTION_MESSAGE, null, null, null);
            if (confirm == JOptionPane.YES_OPTION) {
                System.exit(1);
            }
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                ClosingFrame cf = new ClosingFrame();
                JButton btn = new JButton("Show first JFrame");
                btn.addActionListener(new ActionListener() {

                    public void actionPerformed(ActionEvent e) {
                        frame.setVisible(true);
                    }
                });
                frame1.add(btn, BorderLayout.SOUTH);
                frame1.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
                frame1.setPreferredSize(new Dimension(400, 300));
                frame1.setLocation(100, 400);
                frame1.pack();
                frame1.setVisible(true);
            }
        });
    }
}

Solution 3

You could avoid the listener completely and use

setDefaultCloseOperation(DISPOSE_ON_CLOSE);

Note that the default value is HIDE_ON_CLOSE, so the behavior you want should be the default behavior. Maybe you registered another listener that exits the application.

See http://docs.oracle.com/javase/6/docs/api/javax/swing/JFrame.html#setDefaultCloseOperation%28int%29

Solution 4

It's hard to pinpoint exactly why you are experiencing the behavior stated without seeing a little more of the set-up code, however it may be due to defaultCloseOperation set to EXIT_ON_CLOSE.

Here's a link to a demo displaying the properties you are looking for although the structure is a bit different. Have a look: http://docs.oracle.com/javase/tutorial/uiswing/examples/components/FrameworkProject/src/components/Framework.java

Share:
20,866
Jayyrus
Author by

Jayyrus

I'm an Italian Software Engineer. I like very much to learn and study new technologies

Updated on March 16, 2020

Comments

  • Jayyrus
    Jayyrus about 4 years

    i'm developing a JFrame which has a button to show another JFrame. On the second JFrame i want to override WindowsClosing event to hide this frame but not close all the application. So i do like this:

    On second JFrame

    addWindowListener(new java.awt.event.WindowAdapter() {
        public void windowClosing(java.awt.event.WindowEvent evt) {
             formWindowClosing(evt);
        }
    });
    
    private void formWindowClosing(java.awt.event.WindowEvent evt) {
        this.dispose();
    }
    

    but application still close when i click x button on the windows. why? can you help me?

    I can't use

    setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    

    because i need to show again that JFrame with some information added in it during operations from first JFrame. So i init second JFrame with attribute visible false. if i use dispose i lose the information added in a second moment by the other JFrame. so i use

    private void formWindowClosing(java.awt.event.WindowEvent evt) {
        this.setVisible(false);
    }
    

    but it still continue to terminate my entire app.

  • JB Nizet
    JB Nizet about 12 years
    The default close operation does exactly what your listener does: it hides the frame. I don't see why you could not reuse this frame after.
  • Jayyrus
    Jayyrus about 12 years
    sorry.. i think i didn't explain good my question... i don't want to create a dialog in which user can close window or not. but i only want to hide it. like a button in which i set this.setVisible(false)
  • mKorbel
    mKorbel about 12 years
    @JackTurky I think it seriously with the JDialog :-) JFrames can take parent, cann't be moved toFront/Back (since implemented in API, simple doean't works), you have got issue with Iconified ....
  • Michael
    Michael about 12 years
    With the given edit to the question, this answer is incorrect.
  • Jayyrus
    Jayyrus about 12 years
    no.. just set invisible on close of windows and through a button in main jframe set it visible..
  • mKorbel
    mKorbel about 12 years
    @JackTurky hmmmmmm and now ??? :-), be sure that this.setVisible(false); could be whatever what is focusable on the screen :-)
  • nIcE cOw
    nIcE cOw about 12 years
    hehe, too true, wish I could write code like yours. Hope that day is near :-)
  • nIcE cOw
    nIcE cOw about 12 years
    @JackTurky : Your Welcome and Keep Smiling :-)
  • nIcE cOw
    nIcE cOw about 12 years
    @mKorbel : Wowo, I didn't knew about those stats, Many people with vast knowledge are their like yourself :-)
  • nIcE cOw
    nIcE cOw about 12 years
    @JBNizet : Wish I could upvote this answer, two or more times, seems like what you wanted to explain, OP couldn't understand that, but I just realized, exactly what you were telling him. There is no need for the WindowListener part. I never read about the default behaviour of the Jframe but that doc referred by you, enlightened me :-)