Search code examples
javaswingjoptionpanejcheckbox

JOptionPane.showMessageDialog - Why breaking down checkboxes?


I'm very interested, how to explain this, it's sth like hack? Or there is nothing to be excited about?

Maybe, you had some other, more intresting, experiences like this, when you were a beginer?

Warning! Its not a problem (It was realy helpful!), I just looking for more sense in my code :)

Sooo, in brief: Last if statment bans one checkbox...

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

class NotMain {

    public static void main(String[] args) {
        X x = new X();
    }
}
class X implements ItemListener{
    X() {
        JCheckBox jCheckBox[] = new JCheckBox[2];
        JPanel panel = new JPanel();
        JFrame frame = new JFrame();

        jCheckBox[0] = new JCheckBox("1");
        jCheckBox[1] = new JCheckBox("2");
        jCheckBox[0].addItemListener(this);
        jCheckBox[1].addItemListener(this);

        panel.add(jCheckBox[0]);
        panel.add(jCheckBox[1]);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    private int i;
    @Override
    public void itemStateChanged(ItemEvent e) {
        if (e.getStateChange() == ItemEvent.SELECTED) {
            i++;
        } else i--;

        if (i == 2) {
                  //if you comment next line, you'll be able to select two checkboxes
            JOptionPane.showMessageDialog(null, "nope.");
        }
    }
}

Solution

  • The state of the check box changes when a mousePressed and mouseReleased event is generated for the check box. This is easy to demonstrate. Just do a mousePressed on the check box and then drag the mouse off the check box before releasing the mouse. The state doesn't change.

    In your example the check box knows that a mousePressed and mouseReleased has been done so it generates and itemStateChanged event which causes the JOptionPane to be displayed.

    The problem is that the ItemStateChange code executes before the mouseReleased code. Now when the mouseReleased code is executed the option pane has the focus so the state of the check box is not changed.

    Change your code to:

    if (i == 2)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                   JOptionPane.showMessageDialog(null, "nope.");
            }
        });
    }
    

    Now the display of the option pane is added to the end of the Event Dispatch Thread (EDT) which means both the mousePressed and mouseReleased events are handled by the check box before the JOPtionPane is displayed, so the state of the check box changes to selected.