Class FixedJComboBox<E>

All Implemented Interfaces:
ActionListener, ImageObserver, ItemSelectable, MenuContainer, Serializable, EventListener, Accessible, ListDataListener
Direct Known Subclasses:
ColumnDataComboBox

public class FixedJComboBox<E> extends JComboBox<E>
JComboBox drop-in replacement that fixes an action firing misfeature in the standard implementation.

The problem is to do with firing ActionEvents when the ComboBoxModel is changed. According to the JComboBox.addActionListener(java.awt.event.ActionListener) documentation, ActionListeners should only be informed when a selection is made, that is when the selection changes. In general that's true, an ActionEvent is only fired when the model selection changes, but at least in Oracle Java 8/OpenJDK 8 such an event can be fired if the model content (list data) changes but the current selection is null both before and after that change (if the selection is an particular non-null value before and after, no ActionEvent is fired, as expected). Since there are a lot of listeners on these selectors in topcat, and certain user actions can cause a large number of changes to the model without changing the selection, this can cause a lot of unnecessary events to be fired, which can in some circumstances result in genuine responsiveness issues.

This class overrides the contentsChanged(javax.swing.event.ListDataEvent) method, and enough other methods to make that work, so that no event is fired in the event of a null->null selection change.

Since:
6 Oct 2023
Author:
Mark Taylor
See Also:
  • Constructor Details

    • FixedJComboBox

      public FixedJComboBox()
      Creates a JComboBox with a default data model.
    • FixedJComboBox

      public FixedJComboBox(ComboBoxModel<E> model)
      Creates a JComboBox that takes its items from an existing ComboBoxModel.
      Parameters:
      model - model
    • FixedJComboBox

      public FixedJComboBox(E[] items)
      Creates a JComboBox that contains the elements in the specified array.
      Parameters:
      items - array populating default combo box model
  • Method Details

    • contentsChanged

      public void contentsChanged(ListDataEvent evt)
      Overriding this method is questionable, since the OpenJDK javadoc says: "This method is public as an implementation side effect. do not call or override.". So there could be problems. But if the method exists at all to be overridden, this implementation shouldn't change its behaviour in a bad way, and if it doesn't exist it shouldn't have any effect, so I don't *expect* runtime problems with either OpenJDK or other JDKs.

      However if an attempt is made to compile this class against a JDK in which JComboBox lacks the contentsChanged method, there will be trouble. It could be averted by removing the @Override annotation, and invoking the superclass method using reflection.

      Specified by:
      contentsChanged in interface ListDataListener
      Overrides:
      contentsChanged in class JComboBox<E>
    • setModel

      public void setModel(ComboBoxModel<E> model)
      Overrides:
      setModel in class JComboBox<E>
    • removeAllItems

      public void removeAllItems()
      Overrides:
      removeAllItems in class JComboBox<E>
    • selectedItemChanged

      protected void selectedItemChanged()
      Overrides:
      selectedItemChanged in class JComboBox<E>