Search code examples
javaswingjdialog

How to prevent that closing a JDialog closes the entire application


I have a main(screen) gui window and need to open a few "multi input" windows (jdialog or when not possible jframe), for example to add preferences (4 textfields with 2 filechoosers and 2 radiobuttons). When pressing OK/Cancel in these JDialogs (or JFrames), my entire application closes. I don't want that. How can I prevent that?

First try: I tried the intelliJ option "New -> Create Dialog class", which gives me a JDialog with OK/Cancel button. Pressing one of the buttons closes the JDialog and my entire application.

Second try: I wrote a class "by hand" which creates a JDialog (and also tried JFrame). Again: Pressing one of the buttons closes the JDialog and my entire application.

I removed "dispose()" and "setVisible(false)" options from theJDialog (JFrame), but still my entire application is closed.

main class method

public class mainScreen {

    // Menu action listener (only relevant options)
    class MenuActionListener implements ActionListener {

    // menuListener
    public void actionPerformed(ActionEvent ev) {
            //myVariables myVars = new myVariables();
        String[] dummy = null;
            System.out.println("Selected: " + ev.getActionCommand());

            switch(ev.getActionCommand()) {
                case "Preferences":
                    showPreferencesDialog();
                case "Exit":
                    System.exit(0);
                    break;
    }

    // method that opens the external class (see below in following code block)
    private void showPreferencesDialog() {

        prefJDialog myprefs = new prefJDialog(prefsPanel);
        myprefs.showDialog();
        boolean okPressed = myprefs.isOkPressed();
        if (okPressed) {
            JOptionPane.showMessageDialog(mainScreen.this.rootPanel,"OK pressed","About jExifToolGUI",JOptionPane.INFORMATION_MESSAGE);
        } else {
            JOptionPane.showMessageDialog(mainScreen.this.rootPanel,"Cancel pressed","About jExifToolGUI",JOptionPane.INFORMATION_MESSAGE);
        }
    }

    // This is the class which is mention in the manifest
    public mainScreen(JFrame frame) {
        boolean preferences = false;
        Preferences prefs = Preferences.userRoot();

        createmyMenuBar(frame);
        groupRadiobuttonsandListen();
        fileNamesTableListener();
        try {
            myUtils.DisplayLogo(mainScreen.this.iconLabel);
        } catch(IOException ex) {
            System.out.println("Error reading Logo");
        }

        preferences = check_preferences();
        if (!preferences) {
            myUtils.checkExifTool(mainScreen.this.rootPanel);
        }

        programButtonListeners();
    }
    // main method in my main class for my project
    public static void main(String[] args) {

        JFrame frame = new JFrame("jExifToolGUI");
        frame.setContentPane(new mainScreen(frame).rootPanel);
        //frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

    }
}

The JDialog class/method that is called from the main class

package org.hvdw.jexiftoolgui;

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

public class prefJDialog extends JDialog {
    private JButton okButton;
    private JButton cancelButton;

    private JPanel prefsPanel;

    private boolean okPressed;

    public prefJDialog(JPanel prefsPanel) {
        super(JOptionPane.getFrameForComponent(prefsPanel), true);
        this.prefsPanel = prefsPanel;
        setTitle("Preferences");
        initDialog();
    }

    public void showDialog() {
        setSize(800, 768);
        double x = getParent().getBounds().getCenterX();
        double y = getParent().getBounds().getCenterY();
        setLocation((int) x - getWidth() / 2, (int) y - getHeight() / 2);
        setVisible(true);
    }


    private void initDialog() {
        JPanel pane = new JPanel();
        pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
        pane.setBorder(BorderFactory.createEmptyBorder(10, 10, 5, 10));
        add(pane);

        pane.add(Box.createVerticalGlue());
        FlowLayout l = new FlowLayout(FlowLayout.RIGHT);
        JPanel buttonsPane = new JPanel(l);
        okButton = new JButton("Save"); //$NON-NLS-1$
        buttonsPane.add(okButton);
        pane.getRootPane().setDefaultButton(okButton);
        cancelButton = new JButton("CANCEL"); //$NON-NLS-1$
        buttonsPane.add(cancelButton);

        buttonsPane.setMaximumSize(new Dimension(Short.MAX_VALUE, (int) l.preferredLayoutSize(buttonsPane).getHeight()));
        pane.add(buttonsPane);

        addListeners();
    }

    private void addListeners() {
        okButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //saveProperties();
                setVisible(false);
                okPressed = true;
                //close();


                // dispose();
            }

        });
        cancelButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                setVisible(false);
                //dispose();
                //close();
                okPressed = false;
            }
        });

    }

    public boolean isOkPressed() {
        return okPressed;
    }

    /*public void close() {
        WindowEvent winClosingEvent = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
        Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(winClosingEvent);
    }*/
}

So how do I prevent that upon clicking OK or Cancel in the JDialog, the entire application closes. That needs to stay open until the user clicks the "window close" X in the top-right, or from the menu "File -> Exit"

I have searched Google for several days, but can't find a solution (and one same question without answer).

Edit: After Patrick's answer I changed the close method to

    public void close() {
        this.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
    }

And removed the /* and */. I also activated the close(); in the listeners again, but it doesn't make a difference. My main app is still closed.


Solution

  •      switch(ev.getActionCommand()) {
                case "Preferences":
                    showPreferencesDialog();
                case "Exit":
                    System.exit(0);
                    break;
    

    And the problem is that you don't have a break statement in your switch case so the code falls through to the "Exit" logic and does a System.exit(0)

    This is why we need a proper "MCVE" with every question. When you post random pieces of code we can't see the entire logic flow.