Question

I have made a custom JComboBox. For this I am using a JPopupMenu containing JCheckBoxMenuItem. But apparently the PopupMenuListener popupMenuWillBecomeInvisible are running before the JCheckBoxMenuItem are changed. Any ideas how to fix? I would like not to add listeners to the JCheckBoxMenuItem.

public class ListenerTest  extends JFrame implements ActionListener, PopupMenuListener {

    private JPopupMenu menu;
    private List<JCheckBoxMenuItem> menuItems;

    private JCheckBoxMenuItem i1;
    private JCheckBoxMenuItem i2;
    private JCheckBoxMenuItem i3;

    public ListenerTest(){

        // Create button
        JButton b = new JButton("Click me!");
        b.addActionListener(this);

        // Create Popupmenu
        menu = new JPopupMenu();
        menu.addPopupMenuListener(this);

        // Add CheckBoxes to PopupMenu 
        menuItems = new LinkedList<JCheckBoxMenuItem>();
        i1 = new JCheckBoxMenuItem("1");
        i2 = new JCheckBoxMenuItem("2");
        i3 = new JCheckBoxMenuItem("3");
        menu.add(i1);
        menu.add(i2);
        menu.add(i3);

        this.add(b);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.pack();
        this.setVisible(true);
    }

    public static void main(String[] args){
        new ListenerTest();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // Show PopupMenu when button is clicked
        menu.show(this, 0, this.getHeight());
    }

    @Override
    public void popupMenuWillBecomeVisible(PopupMenuEvent e) {}

    @Override
    public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
        // Check which checkBoxes is checked when popup menu is closed(currently one step behind)
        System.out.println(i1.isSelected());
        System.out.println(i2.isSelected());
        System.out.println(i3.isSelected());
    }

    @Override
    public void popupMenuCanceled(PopupMenuEvent e) {}
}
Was it helpful?

Solution

One "possible" solution vs. a kludge, is use your popupMenuWillBecomeInvisible(...) but queue your checking of the state onto the Swing event queue so that it performs its action later, after all items currently on the event queue have finished. This is not guaranteed to work however.

@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {

  SwingUtilities.invokeLater(new Runnable() {
     public void run() {
        System.out.println(i1.isSelected());
        System.out.println(i2.isSelected());
        System.out.println(i3.isSelected());
     }
  });
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top