Search code examples
javaswingdisposejdialog

JDialog refuses to close


I am busy making a basic Java word processor as a personal project, and it includes a popup JDialog. However, when the user clicks the 'Cancel' button, the JDialog refuses to close and the only way to close it is with the Close button on the frame itself. Similarly, when the 'Confirm' button is activated, the task is completed but the JDialog stays open. Can anyone help? My JDialog init code:

    package cword;

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

    public class AlreadyExists extends JDialog
    {
        public static final long serialVersionUID = 1L;
        public AlreadyExists(Frame owner, String pathname, String filename, boolean includedExtension)
        {
            super(owner);
            initComponents(pathname, filename, includedExtension);
        }

        private void initComponents(final String pathname, String filename, final boolean includedExtension)
        {
            dialogPane = new JPanel();
            contentPanel = new JPanel();
            label1 = new JLabel();
            buttonBar = new JPanel();
            okButton = new JButton();
            cancelButton = new JButton();

            setTitle("Confirm Overwrite");
            Container contentPane = getContentPane();
            contentPane.setLayout(new BorderLayout());

            {

                dialogPane.setLayout(new BorderLayout());

                {
                    contentPanel.setLayout(null);

                    label1.setText("File " + filename + " already exists. Are you sure you want to overwrite?");
                    contentPanel.add(label1);
                    label1.setBounds(new Rectangle(new Point(0, 5), label1.getPreferredSize()));

                    {
                        Dimension preferredSize = new Dimension();
                        for(int i = 0; i < contentPanel.getComponentCount(); i++) {
                            Rectangle bounds = contentPanel.getComponent(i).getBounds();
                            preferredSize.width = Math.max(bounds.x + bounds.width, preferredSize.width);
                            preferredSize.height = Math.max(bounds.y + bounds.height, preferredSize.height);
                        }
                        Insets insets = contentPanel.getInsets();
                        preferredSize.width += insets.right;
                        preferredSize.height += insets.bottom;
                        contentPanel.setMinimumSize(preferredSize);
                        contentPanel.setPreferredSize(preferredSize);
                    }
                }
                dialogPane.add(contentPanel, BorderLayout.CENTER);

                {
                    buttonBar.setBorder(new EmptyBorder(12, 0, 0, 0));
                    buttonBar.setLayout(new GridBagLayout());
                    ((GridBagLayout)buttonBar.getLayout()).columnWidths = new int[] {0, 85, 80};
                    ((GridBagLayout)buttonBar.getLayout()).columnWeights = new double[] {1.0, 0.0, 0.0};

                    okButton.setText("Confirm");
                    buttonBar.add(okButton, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0,
                        GridBagConstraints.CENTER, GridBagConstraints.BOTH,
                        new Insets(0, 0, 0, 5), 0, 0));

                    cancelButton.setText("Cancel");
                    buttonBar.add(cancelButton, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0,
                        GridBagConstraints.CENTER, GridBagConstraints.BOTH,
                        new Insets(0, 0, 0, 0), 0, 0));
                }
                dialogPane.add(buttonBar, BorderLayout.SOUTH);
            }
            contentPane.add(dialogPane, BorderLayout.CENTER);
            pack();
            setLocationRelativeTo(getOwner());
            setDefaultCloseOperation(2);
            setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
            setVisible(true);
            okButton.addActionListener(new ActionListener()
            {
                public void actionPerformed(ActionEvent ae)
                {
                    write(pathname, includedExtension);
                    close();
                }
            });
            cancelButton.addActionListener(new ActionListener()
            {
                public void actionPerformed(ActionEvent ae)
                {
                    close();
                }
            });
        }

        private void write(String pathname, boolean includedExtension)
                {
            if(includedExtension)
            {
                try
                {
                    BufferedWriter writer;
                    writer = new BufferedWriter(new FileWriter(pathname));
                    writer.write(CWord.textArea1.getText());
                    writer.close();
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                }
            }
            else if(!includedExtension)
            {
                try
                {
                    BufferedWriter writer;
                    writer = new BufferedWriter(new FileWriter(pathname + ".txt"));
                    writer.write(CWord.textArea1.getText());
                    writer.close();
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                }
            }
        }
        private void close()
        {
            dispose();
            dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
        }

        private JPanel dialogPane;
        private JPanel contentPanel;
        private JLabel label1;
        private JPanel buttonBar;
        private JButton okButton;
        private JButton cancelButton;
    }

And one of the lines that call this in CWord.class:

    new AlreadyExists(this, file.getAbsolutePath(), file.getName(), true);

Solution

  • OK, this was a tough one, but I finally figured it out!

    Here's your problem. You're adding the ActionListeners to the buttons after you call setVisible(true). Since this is a modal dialog, setVisible(true) is a blocking call on the EDT. This means that the code after setVisible(true) isn't executed until after the dialog is closed, so the ActionListeners aren't being added to the button until after the dialog is closed.

    You should always have your call to setVisible() after all the GUI initialization is performed when it's a modal dialog. So just move setVisible(true) to after the calls to addActionListener on the buttons, and you'll be good to go.