Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4760078

JComboBox with empty item list generates spurious ActionEvent when focus lost

XMLWordPrintable

    • b32
    • x86
    • windows_2000



      Name: sv35042 Date: 10/08/2002


      FULL PRODUCT VERSION :
      java version "1.4.0"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
      Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)

      FULL OPERATING SYSTEM VERSION :
      Microsoft Windows 2000 [Version 5.00.2195]

      EXTRA RELEVANT SYSTEM CONFIGURATION :
      Not applicable

      A DESCRIPTION OF THE PROBLEM :
      A JComboBox with an empty item list generates a spurious
      ActionEvent when the focus is lost. I think this occurs
      because:

      a) getItem() in BasicComboBoxEditor will never return
      null, as can be seen from the following lines 61-81:
          public Object getItem() {
              Object newValue = editor.getText();
              
              if (oldValue != null && !(oldValue instanceof
      String)) {
                  // The original value is not a string. Should
      return the value in it's
                  // original type.
                  if (newValue.equals(oldValue.toString())) {
                      return oldValue;
                  } else {
                      // Must take the value from the editor and
      get the value and cast it to the new type.
                      Class cls = oldValue.getClass();
                      try {
                          Method method = cls.getMethod
      ("valueOf", new Class[]{String.class});
                          newValue = method.invoke(oldValue, new
      Object[] { editor.getText()});
                      } catch (Exception ex) {
                          // Fail silently and return the
      newValue (a String object)
                      }
                  }
              }
              return newValue;
          }

      b) focusLost in EditorFocusListener in BasicComboBoxUI
      only ducks out for the above returning null, or the
      currently selection item equaling the Editor item, as can
      be seen from lines 1559-1569 of the code:
              public void focusLost( FocusEvent e ) {
      ComboBoxEditor editor = comboBox.getEditor();
                  Object item = editor.getItem();

                  if (!e.isTemporary() && item != null &&
      !item.equals( comboBox.getSelectedItem())) {
                      comboBox.actionPerformed
                          (new ActionEvent(editor, 0, "",
                                           
      EventQueue.getMostRecentEventTime(), 0));
                  }
              }

      Seeing as the item returned by the editor is never null,
      while the selected item from an empty list is null, the
      optout condition is not met, and a spurious event is
      generated.

      The following code demos this. Compile and run it, click
      in the combo, then click in the text area. An event is
      generated the first time this is attempted, because the
      item list is still empty. On subsequent trials, the list
      now has one spurious blank entry generated by the first try
      bug, and the optout condition then works as it is
      comparing two blank strings.

      I think the Editor should return a null where no input has
      ever been received. This would avoid the problem.


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      See full description

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      See full description

      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.awt.*;
      import java.awt.event.*;
      import javax.swing.*;

      public class ComboBoxDemo extends JFrame
      {
      public static void main( String args[] )
      {
      JFrame frame = new ComboBoxDemo("JComboBox Bug Demo");
      }

      public ComboBoxDemo( String aTitle )
      {
      super( aTitle );
      addWindowListener(
      new WindowAdapter()
      {
      public void
      windowClosing( WindowEvent e )
      {

      System.exit(0);
      }
      }
      );

      MyComboBox theComboBox = new MyComboBox();
      getContentPane().setLayout( new BorderLayout() );
      getContentPane().add( new JTextArea( "Something that can
      receive focus ..." ), BorderLayout.CENTER );
      getContentPane().add( theComboBox, BorderLayout.SOUTH );

      pack();
      theComboBox.requestFocus();
      setVisible(true);
      }

      protected class MyComboBox extends JComboBox
      {
      protected MyComboBox()
      {
      super();
      setEditable( true );
      addActionListener (
      new
      ActionListener()

      {

      public void actionPerformed( ActionEvent ae )

      {

      System.out.println( "ActionEvent:" + ae );

      String input = getInput();

      System.out.println( "Input: " + input );

      }

      }
      );
      } // protected MyComboBox()

      protected String getInput()
      {
      String theInput = (String)getEditor().getItem();

      insertItemAt( theInput, 0 );
      for( int i = 1; i < getItemCount(); i++ )
      if( theInput.equalsIgnoreCase( (String)getItemAt
      (i) ) )
      removeItemAt( i-- );
      while( getItemCount() > PREVIOUSCOMMANDS )
      removeItemAt( PREVIOUSCOMMANDS );

      setSelectedIndex(0);
      getEditor().selectAll();

      return theInput;
      }

      // The maximum number of previous commands to remember
      private final int PREVIOUSCOMMANDS = 10;

      } // protected class MyComboBox extends JComboBox
      }

      ---------- END SOURCE ----------

      CUSTOMER WORKAROUND :
      It's trivial if you don't mind having at least one item in
      the list from the start, but if you do, then there's no
      easy workaround.

      I tried extending BasicComboBoxEditor to override getItem
      (), but was screwed by the fact that oldValue is private
      access ( it's the sort of value that should be protected,
      not private )
      (Review ID: 143279)
      ======================================================================

            draskinsunw Daniel Raskin (Inactive)
            svioletsunw Scott Violet (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: