问题描述:

I have 2 JComboBox controls filled with items initially. Selecting one item in a JComboBox moves it to the other JComboBox.

The problem occurs when one of the JComboBox controls is empty. When I try to move an item to an empty JComboBox it triggers its actionPerformed event.

private void leftComboActionPerformed(java.awt.event.ActionEvent evt) {

Object selectedItem = leftCombo.getSelectedItem();

leftCombo.removeItem(selectedItem);

rightCombo.addItem(selectedItem);

}

private void rightComboActionPerformed(java.awt.event.ActionEvent evt) {

Object selectedItem = rightCombo.getSelectedItem();

rightCombo.removeItem(selectedItem);

leftCombo.addItem(selectedItem);

}

Why does adding an item to the empty JComboBox do that? It doesn't fire when an item is added to it when it's filled.

How to prevent the event from firing when it's empty?

网友答案:

The following piece of code dumps the stack trace

import javax.swing.JComboBox;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class EmptyComboboxTest {
  public static void main( String[] args ) {
    EventQueue.invokeLater( new Runnable() {
      @Override
      public void run() {
        JComboBox<String> emptyBox = new JComboBox<String>();
        emptyBox.addActionListener( new ActionListener() {
          @Override
          public void actionPerformed( ActionEvent e ) {
            Thread.dumpStack();
          }
        } );
        emptyBox.addItem( "test" );
      }
    } );
  }
}

The relevant part of it

at javax.swing.JComboBox.fireActionEvent(JComboBox.java:1260)
at javax.swing.JComboBox.contentsChanged(JComboBox.java:1331)
at javax.swing.AbstractListModel.fireContentsChanged(AbstractListModel.java:118)
at javax.swing.DefaultComboBoxModel.setSelectedItem(DefaultComboBoxModel.java:94)
at javax.swing.DefaultComboBoxModel.addElement(DefaultComboBoxModel.java:132)

If you then look in the source code, you can see that when adding an element it will be selected when there is currently nothing selected

    if ( objects.size() == 1 && selectedObject == null && anObject != null ) {
        setSelectedItem( anObject );
    }

Changing the selection might cause the firing of an ActionEvent. If you follow the source code there is no mechanism to disable this. You could however disable your listener before you add the element, and enable it afterwards.

网友答案:

The way to avoid the actionPerformed event is to use the combo box's model, which is an instance of the javax.swing.ComboBoxModel interface.

E.g. the DefaultComboBoxModel implementation allows you to add/remove elements to/from the model. You get the model, work on it and, when the model is ready, you set it back to the combo box.

相关阅读:
Top