Java Swing Combobox removeAllItems calling ItemStateChanged also?

霸气de小男生 提交于 2019-12-01 10:48:24

As nIcE cOw already illustrated in his example, it should certainly work when you use a DefaultComboBoxModel (which is the case in his sample code, although it happens behind the screens).

I could explain the behavior you encounter for the non-DefaultComboBoxModel case, although your code snippet suggests you use one. Looking at the source code for JComboBox#removeAllItems there is a different code path since the removeAllElements method is not part of the MutableComboBoxModel interface

public void removeAllItems() {
    checkMutableComboBoxModel();
    MutableComboBoxModel<E> model = (MutableComboBoxModel<E>)dataModel;
    int size = model.getSize();

    if ( model instanceof DefaultComboBoxModel ) {
        ((DefaultComboBoxModel)model).removeAllElements();
    }
    else {
        for ( int i = 0; i < size; ++i ) {
            E element = model.getElementAt( 0 );
            model.removeElement( element );
        }
    }
    selectedItemReminder = null;
    if (isEditable()) {
        editor.setItem(null);
    }
}

So with a non-DefaultComboBoxModel you are going to remove the items one by one. This means that at a certain point in time, you will remove the selected element. A possible implementation of your model might change the selected element at that point. If you look for example at the implementation in DefaultComboBoxModel (although this code will not be triggered) you can clearly see it changes the selection.

public void removeElementAt(int index) {
    if ( getElementAt( index ) == selectedObject ) {
        if ( index == 0 ) {
            setSelectedItem( getSize() == 1 ? null : getElementAt( index + 1 ) );
        }
        else {
            setSelectedItem( getElementAt( index - 1 ) );
        }
    }

    objects.removeElementAt(index);

    fireIntervalRemoved(this, index, index);
}

Perhaps your model does something similar, which explains the event. Just for making this post complete, the code behind the DefaultComboBoxModel#removeAllElements where you can clearly see it sets the selection to null and does not select another object. Only weird thing in that code is that it does not fire a DESELECTED event first, although you know the selection has changed if you listen for the intervalRemoved event ... but that is not really relevant to your problem

public void removeAllElements() {
    if ( objects.size() > 0 ) {
        int firstIndex = 0;
        int lastIndex = objects.size() - 1;
        objects.removeAllElements();
        selectedObject = null;
        fireIntervalRemoved(this, firstIndex, lastIndex);
    } else {
        selectedObject = null;
    }
}

So to conclude: I say the solution for your problem is located in your model, and not in the code you posted

Here check this code out, this works flawlessly, might be you doing something wrong where you calling removeAllItems() :

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

public class ComboState 
{
    private void createAndDisplayGUI()
    {
        JFrame frame = new JFrame("Combo State Testing : ");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        final JComboBox cbox = new JComboBox();
        cbox.addItem("One");
        cbox.addItem("Two");
        cbox.addItem("Three");
        cbox.addItem("Four");
        cbox.addItemListener(new ItemListener()
        {
            public void itemStateChanged(ItemEvent ie)
            {
                if (ie.getStateChange() == ItemEvent.SELECTED)
                {
                    System.out.println("Item Selected is : " + ie.getItem());
                }
                /*else
                {
                    System.out.println("I am called for other reasons.");
                }*/
            }
        });

        /*
         * Click me to remove JComboBox's items.
         */
        JButton removeButton = new JButton("REMOVE");
        removeButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ae)
            {
                cbox.removeAllItems();
            }
        });

        frame.add(cbox, BorderLayout.CENTER);
        frame.add(removeButton, BorderLayout.PAGE_END);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new ComboState().createAndDisplayGUI();
            }
        });
    }
}

One quick way to do is to have a bool set to true before you call removeAllItem() and back false after. Execute the code in your itemStateChanged() only if the bool variable is false.

Ideally you could override the removeAllItem() function.

not clear from whole discusion,

  • you have to remove all Listener(s) from JComboBox before removing all Items, after Items are removed you can add Listener(s) back,

  • still not sure if you want to add & remove Items dynamically, or you can set whatever value for another JComponent(s),

  • (against complicating simple things) did you see there remove,

.

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);
    }
}

The method removeAllItems does not call ItemStateChanged, but it call actionPerformed, you can check it by running this simple code:

public class Tuto {

    public static void main(String[] args) {
        //create the main frame
        JFrame frame = new JFrame();
        frame.setResizable(false);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setLayout(null);
        frame.setLocation(new Point(10, 10));
        frame.setPreferredSize(new Dimension(400, 300));

        JComboBox<String> combo = new JComboBox();
        combo.addItem("item 1");
        combo.addItem("item 2");
        combo.addItem("item 3");
        combo.setBounds(50, 30, 300, 20);
        combo.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                System.out.println(" action Performed ");
            }
        });
        frame.add(combo);

        JButton button = new JButton("Remove");
        button.setBounds(50, 100, 100, 30);
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                combo.removeAllItems();
            }
        });
        frame.add(button);

        frame.pack();
        frame.setVisible(true);
    }

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!