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

RFE: Editable JComboBox behaves incorrectly when selecting item from the popup

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Unresolved
    • Icon: P5 P5
    • None
    • 1.4.0
    • client-libs



      Name: ddT132432 Date: 12/03/2001


      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-beta3-b84)
      Java HotSpot(TM) Client VM (build 1.4.0-beta3-b84, mixed mode)

      I believe an editable JComboBox should behave differently.

      Currently, the JComboBox will register itself as an action listener with
      its editor. When the JComboBox receives an action event from the editor,
      triggered by the RETURN key being pressed, it takes the edited item from
      the editor and sets it as the selected item in its model ( Code Listing 1).
      The popup is also closed and a "comboBoxEdited" action is fired.

      ------------------------------------------------------------------------
      Code Listing 1: The actionPerformed() method of the JComboBox. This
      method is called by the editor.

      /**
      * This method is public as an implementation side effect.
      * do not call or override.
      */
      public void actionPerformed(ActionEvent e) {
       Object newItem = getEditor().getItem();
       setPopupVisible(false);
       getModel().setSelectedItem(newItem);
       String oldCommand = getActionCommand();
       setActionCommand("comboBoxEdited");
       fireActionEvent();
       setActionCommand(oldCommand);
      }
      ------------------------------------------------------------------------

      This logic seems correct when your purpose is for users to have the option
      of selecting from the items in your JComboBox as well as a user defined
      value.

      HOWEVER, I expect an editable JComboBox to behave differently.

      Often times an editable JComboBox is used to search a database. After a
      value is entered, that value will be compared against the database and the
      JComboBox will then be populated with the results. If the result has only
      one item, that item will automatically be selected. If the result contains
      more than one item, the popup will be displayed and the user may scroll and
      select the appropriate item. An alternative to this is to automatically
      select the first item of the results and allow for the user to initiate
      the popup and select an alternate item.

      I have been struggling through many versions of the JDK to provide this sort
      of functionality on a JComboBox but have encountered many road blocks. This
      posting is concerned with the JAVA 2 SDK 1.4 Beta 3, although previous
      versions apply.

      There has been progress towards defining the functionality of an editable
      JComboBox within this version. Most important are the "comboBoxEdited" action
      command that is fired and the PopupMenuListener support. The PopupMenuListener
      does not seem to help in my situation. The comboBoxEdited command is a great
      leap forward, but still may have issues.

      By using the "comboBoxEdited" action, one may now define an action to occur
      specifically when an edit has occured. (In previous versions of the SDK
      developers were unable to distinguish between an action fired by the editor and
      an action fired when a new item was selected.) The spirit of this would suggest
      that one could now simply provide an action listener to support the
      functionality I seek ( See Code Listing 2 ).


      ------------------------------------------------------------------------------
      /*
      Code Listing 2 :
      This implementation of an editable JComboBox uses an action listener to
      re-populate the JComboBox with items based on the value entered in the editor.
      It is meant to simulate a JComboBox that allows users to enter a value and
      then select from matching results on a database.
      */

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

      public class JComboBoxTest extends JComboBox {

         public static void main ( String[] args ) {
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            
            //create editable JComboBox
            JComboBox combo = new JComboBoxTest();
            combo.setEditable(true);
            //Add ActionListener for comboBoxEdited actions
            combo.addActionListener(
               new ActionListener() {
                  public void actionPerformed(ActionEvent e) {
                     JComboBox c = (JComboBox)e.getSource();
                     //Exchange the if command with the following to account for popup visibility
                     //if ( "comboBoxEdited".equals(e.getActionCommand()) && !c.isPopupVisible() ) {
                     if ( "comboBoxEdited".equals(e.getActionCommand()) ) {
                        /*
                        Search code goes here. This could be a query to
                        a database or some other search operation.
                        Our implementation will set a new model with
                        values based on the search string.
                        */
                        Vector v = new Vector();
                        //get String to search from editor
                        String searchString = (String)c.getEditor().getItem();
                        for(int i = 0 ; i < 10 ; i++) {
                           v.add(searchString + " " + i);
                        }
                        c.setModel(new DefaultComboBoxModel(v));
                     }
                  }
               }
            );
        
            //Add combo to content pane
            Container c = f.getContentPane();
            c.setLayout(new BorderLayout());
            c.add( combo , BorderLayout.CENTER);
            f.pack();
            f.setVisible(true);
         }

         /*
         The following actionPerformed code hides the popup
         after firing the action command.
         Uncomment the following to allow this code to work
         properly.
         */
         /*
         public void actionPerformed(ActionEvent e) {
            Object newItem = getEditor().getItem();
            getModel().setSelectedItem(newItem);
            String oldCommand = getActionCommand();
            setActionCommand("comboBoxEdited");
            fireActionEvent();
            setActionCommand(oldCommand);
            setPopupVisible(false);
         }
         */

      }

      ---------------------------------------------------------------------


      The problem with this code is that the comboBoxEdited action is fired after an
      edit but also after an item is selected when scrolling through the values in
      the popup. When you first enter a value and hit return, the combobox is
      populated with new items, the first item is selected, and everything is groovy.
      If you then scroll down and select another item by hitting RETURN, a search is
      triggered once again.

        To counter this, one may use the commented "if" statement which takes into
      account popup visibility. However, due to placement of the setPopupVisible
      method in the actionPerformed method of the JComboBox, this still will not
      work. Uncomment the "actionPerformed" method in Listing 2 to fix this bug.
      The only difference between this code and the official code is the placement
      of the setPopupVisible statement.

      Therefore, I am recommending that the setPopupVisible call be relocated to
      after the comboBoxEdited action is fired in the actionPerformed method of
      the JComboBox. By doing this, it may be easier to support the current
      functionality of an editable JComboBox as well as the functionality which
      I have suggested.

      I may even suggest that the the actionPerformed method be removed altogether.
      Why must the JComboBox dictate what the editor does and how it effects the
      popup and the model? It would be much simpler for developers to define this
      themselves. If I want to do something when an edit occurs, I would add an
      action listener for "comboBoxEdited". When considering the MVC Architecture,
      should not this code exist in the ComboBoxUI in the first place? Isn't this
      why the actionPerfomed method warns "This method is public as an implementation
      side effect - do not call or override"?


      Some related Bugs:
      http://developer.java.sun.com/developer/bugParade/bugs/4515752.html
      http://developer.java.sun.com/developer/bugParade/bugs/4337071.html

      Some related Links:
      http://java.sun.com/docs/books/tutorial/uiswing/components/combobox.html
      http://java.sun.com/j2se/1.4/docs/api/javax/swing/JComboBox.html
      (Review ID: 135793)
      ======================================================================

            Unassigned Unassigned
            ddressersunw Daniel Dresser (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Imported:
              Indexed: