Search code examples
javaswingmessageboxevent-dispatch-thread

Showing message dialog in ItemListener prevents checkbox selection


I noticed that when using a message box in an ItemListener when selecting a checkbox, it will prevent the checkbox from becoming selected. Here is a full example demonstrating the problem:

import javax.swing.*;

import static java.awt.event.ItemEvent.SELECTED;
import static javax.swing.JOptionPane.INFORMATION_MESSAGE;
import static javax.swing.JOptionPane.showMessageDialog;

public class ExampleFrame extends JFrame
{
    private ExampleFrame()
    {
        JCheckBox jCheckBox = new JCheckBox("Fail");
        add(jCheckBox);

        jCheckBox.addItemListener(itemEvent ->
        {
            int stateChange = itemEvent.getStateChange();
            if (stateChange == SELECTED)
            {
                showMessageDialog(rootPane,
                        "The checkbox selection did not work.",
                        "SSCCE",
                        INFORMATION_MESSAGE);
            }
        });
    }

    public static void main(String[] arguments)
    {
        ExampleFrame exampleFrame = new ExampleFrame();
        exampleFrame.pack();
        exampleFrame.setVisible(true);
    }
}

What would be best practise to fix this code to make it show the message box and does not break selecting the checkbox?

I had success with using an additional thread to execute the listener, delay it by e.g. 100 milliseconds and then execute the message box again on the EDT. This seems too hacky to be considered a proper solution though.

This question is related but did not receive a decent answer.


Solution

  • Surround your modal dialog with SwingUtilities.invokeLater

    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            showMessageDialog(rootPane,
                "The checkbox selection did not work.",
                "SSCCE",
                INFORMATION_MESSAGE);
        }
    });