JCheckbox - ActionListener and ItemListener?

For reference, here's an sscce that illustrates the difference. Console:

SELECTED
ACTION_PERFORMED
DESELECTED
ACTION_PERFORMED

Code:

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;

/** @see http://stackoverflow.com/q/9882845/230513 */
public class Listeners {

    private void display() {
        JFrame f = new JFrame("Listeners");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JCheckBox b = new JCheckBox("JCheckBox");
        b.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println(e.getID() == ActionEvent.ACTION_PERFORMED
                    ? "ACTION_PERFORMED" : e.getID());
            }
        });
        b.addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
                System.out.println(e.getStateChange() == ItemEvent.SELECTED
                    ? "SELECTED" : "DESELECTED");
            }
        });
        JPanel p = new JPanel();
        p.add(b);
        f.add(p);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new Listeners().display();
            }
        });
    }
}

Both ItemListener as well as ActionListener, in case of JCheckBox have the same behaviour. However, major difference is ItemListener can be triggered by calling the setSelected(true) on the checkbox. As a coding practice do not register both ItemListener as well as ActionListener with the JCheckBox, in order to avoid inconsistency.


The difference is that ActionEvent is fired when the action is performed on the JCheckBox that is its state is changed either by clicking on it with the mouse or with a space bar or a mnemonic. It does not really listen to change events whether the JCheckBox is selected or deselected.

For instance, if JCheckBox c1 (say) is added to a ButtonGroup. Changing the state of other JCheckBoxes in the ButtonGroup will not fire an ActionEvent on other JCheckBox, instead an ItemEvent is fired.

Final words: An ItemEvent is fired even when the user deselects a check box by selecting another JCheckBox (when in a ButtonGroup), however ActionEvent is not generated like that instead ActionEvent only listens whether an action is performed on the JCheckBox (to which the ActionListener is registered only) or not. It does not know about ButtonGroup and all other selection/deselection stuff.