Search code examples
swingdebuggingjdialogjava

potential bug in java7 swing using openjdk 1.7.0_101


When using the dispose() method of a JDialog, I get two windowClosed events for the first JDialog closed, and for subsequent JDialogs I get an additional close events for each of the previously closed JDialogs (plus two more for the new JDialog).

Is there something wrong in my code (posted below)?

package main;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.JButton;
import javax.swing.JDialog;

public class Main
{

    public static void main(String[] args) throws InterruptedException
    {
        JDialog dialog;
        while (true)
        {
            dialog = createDialog();
            while (dialog.isVisible())
            {
                Thread.sleep(10);
            }
        }
    }

    public static JDialog createDialog()
    {
        final JDialog dialog = new JDialog();

        JButton close = new JButton("Close");
        dialog.add(close);

        final WindowListener windowListener = new WindowListener() {

            @Override
            public void windowOpened(WindowEvent e) {
                System.err.println("windowOpened " + dialog.hashCode());
            }

            @Override
            public void windowIconified(WindowEvent e) {
                System.err.println("windowIconified " + dialog.hashCode());
            }

            @Override
            public void windowDeiconified(WindowEvent e) {
                System.err.println("windowDeiconified " + dialog.hashCode());
            }

            @Override
            public void windowDeactivated(WindowEvent e) {
                System.err.println("windowDeactivated " + dialog.hashCode());
            }

            @Override
            public void windowClosing(WindowEvent e) {
                System.err.println("windowClosing " + dialog.hashCode());
            }

            @Override
            public void windowClosed(WindowEvent e) {
                System.err.println("windowClosed " + dialog.hashCode());

                // uncommenting this provides a fix to the bug
                // dialog.removeWindowListener(this);
            }

            @Override
            public void windowActivated(WindowEvent e) {
                System.err.println("windowActivated " + dialog.hashCode());
            }
        };

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

        dialog.addWindowListener(windowListener);

        dialog.pack();
        dialog.setVisible(true);
        return dialog;
    }
}

Example output of this code after closing one JDialog box:

windowOpened 1479616934
windowActivated 1479616934
windowDeactivated 1479616934
windowClosed 1479616934
windowClosed 1479616934
windowOpened 1514973352
windowActivated 1514973352

Example output after closing the second JDialog box:

windowClosed 1514973352
windowClosed 1479616934
windowClosed 1514973352
windowOpened 78938440
windowActivated 78938440
  • Affected versions: OpenJDK 1.7.0_101, but not OpenJDK 1.8.0_91
  • Affected by JRE but not by Javac

Solution

  • A dialog will be linked to its owner, and if no owner is given on dialog creation, this can affect the dialog's behavior, as you're seeing. Best to always associate your dialogs with proper owners (or with a well-casted null) for best behavior.