javaswingjcomboboxactionlistenercomboboxmodel

Is there a way to prevent action listeners from firing when setSelectedItem() is called?


I have a program with multiple comboboxes, each with their own action listener. Selecting an item from any of the comboboxes will change the items in one or more of the other comboboxes. The problem I'm running into is that calling setSelectedItem() for one combobox will fire the action listener for another combobox, which in turn fires the action listeners of the other ones, etc etc.

Is there a way to avoid this, either by only allowing the action listeners to be fired from user input, or by detecting that the action was not fired from user input? Say that not using setSelectedItem() is not an option, because I want the program to be able to set the currently selected item for each comboxbox. Thanks in advance for any help.


Solution

  • for example

    import java.awt.*;
    import java.awt.event.*;
    import java.util.*;
    import javax.swing.*;
    
    public class ComboBoxTwo extends JFrame implements ActionListener, ItemListener {
    
        private static final long serialVersionUID = 1L;
        private JComboBox mainComboBox;
        private JComboBox subComboBox;
        private Hashtable<Object, Object> subItems = new Hashtable<Object, Object>();
    
        public ComboBoxTwo() {
            String[] items = {"Select Item", "Color", "Shape", "Fruit"};
            mainComboBox = new JComboBox(items);
            mainComboBox.addActionListener(this);
            mainComboBox.addItemListener(this);
            //prevent action events from being fired when the up/down arrow keys are used
            //mainComboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
            getContentPane().add(mainComboBox, BorderLayout.WEST);
            subComboBox = new JComboBox();//  Create sub combo box with multiple models
            subComboBox.setPrototypeDisplayValue("XXXXXXXXXX"); // JDK1.4
            subComboBox.addItemListener(this);
            getContentPane().add(subComboBox, BorderLayout.EAST);
            String[] subItems1 = {"Select Color", "Red", "Blue", "Green"};
            subItems.put(items[1], subItems1);
            String[] subItems2 = {"Select Shape", "Circle", "Square", "Triangle"};
            subItems.put(items[2], subItems2);
            String[] subItems3 = {"Select Fruit", "Apple", "Orange", "Banana"};
            subItems.put(items[3], subItems3);
    //      mainComboBox.setSelectedIndex(1);
        }
    
        @Override
        public void actionPerformed(ActionEvent e) {
            String item = (String) mainComboBox.getSelectedItem();
            Object o = subItems.get(item);
            if (o == null) {
                subComboBox.setModel(new DefaultComboBoxModel());
            } else {
                subComboBox.setModel(new DefaultComboBoxModel((String[]) o));
            }
        }
    
        @Override
        public void itemStateChanged(ItemEvent e) {
            if (e.getStateChange() == ItemEvent.SELECTED) {
                if (e.getSource() == mainComboBox) {
                    if (mainComboBox.getSelectedIndex() != 0) {
                        FirstDialog firstDialog = new FirstDialog(ComboBoxTwo.this,
                                mainComboBox.getSelectedItem().toString(), "Please wait,  Searching for ..... ");
                    }
                } 
            }
        }
    
        private class FirstDialog extends JDialog {
    
            private static final long serialVersionUID = 1L;
    
            FirstDialog(final Frame parent, String winTitle, String msgString) {
                super(parent, winTitle);
                setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
                JLabel myLabel = new JLabel(msgString);
                JButton bNext = new JButton("Stop Processes");
                add(myLabel, BorderLayout.CENTER);
                add(bNext, BorderLayout.SOUTH);
                bNext.addActionListener(new ActionListener() {
    
                    @Override
                    public void actionPerformed(ActionEvent evt) {
                        setVisible(false);
                    }
                });
                javax.swing.Timer t = new javax.swing.Timer(1000, new ActionListener() {
    
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        setVisible(false);
                    }
                });
                t.setRepeats(false);
                t.start();
                setLocationRelativeTo(parent);
                setSize(new Dimension(400, 100));
                setVisible(true);
            }
        }
    
        public static void main(String[] args) {
            JFrame frame = new ComboBoxTwo();
            frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    }