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

BasicComboBoxUI incorrectly does setSelectedIndex(0) on model change

    XMLWordPrintable

Details

    • beta
    • generic, x86
    • generic, windows_nt

    Description



      Name: krT82822 Date: 01/18/99


      Calling JComboBox.setModel(...) causes a property change event,
      which fires BasicComboPopup$PropertyChangeHandler.propertyChange().
      which incorrectly calls JComboBox.setSelectedIndex(0).
      <P>
      This is a violation of MVC paradigm. Our model is pre-initialized
      to a correct index, and it is incorrect for that to be changed
      without explicit user input.
      <P>
      I believe this line of code was added as a hack to address problems
      with the ComboBox not updating when the model is replaced (ie. bug
      4102887). It caused faulty behaviour (see bug 4150466) and so was
      wrapped in another hack, solving that problem but not the one I am
      reporting. Bug 4112728 requests getting the docs to match the
      unexpected behaviour, which is obviously less optimal then
      getting the behaviour to match the expected.
      <P>
      Please solve the problem of getting the UI to redisplay in a manner
      which does not change the model's state (ie. query instead of
      forcing it). Not rocket science, and won't affect the API.
      (Review ID: 52831)
      ======================================================================

      Name: krT82822 Date: 07/06/99


      Since Swing 1.1, the first item in the model is selected in a
      combo box when the model changes. This code is in
      javax.swing.plaf.BasicComboPopup 1.21
      (distributed with Swing 1.1.1 beta 3), line 615.

      It doesn't ever call getSelectedItem() on the model to see
      what the model thinks the selected item ought to be
      initially, instead ignoring this and setting the selected item to
      the first item (causing the selected item to change in the model)

      The following source code demonstrates this problem. When
      MyModel is instantiated, the selected item is "Three" inside
      the model. However calling setModel() on the combo box causes
      the selection to be changed in the model to 0, and the model's
      concept of selection is completely ignored.


      -- Start sample code ---

      package oracle.bm.propertydialog.test;

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

      /**
       * Demonstrate Swing 1.1 bug with combo selection
       * @author ###@###.###
       */
      public class ComboBugTest implements ActionListener
      {
         private JComboBox m_combo;


         public void doStuff()
         {
            JFrame fraDemo = new JFrame("Demo");
            
            JButton butAllChange = new JButton("Change Model");
            
            m_combo = new JComboBox();
            
            fraDemo.getContentPane().setLayout(new BorderLayout());
            fraDemo.getContentPane().add(m_combo, BorderLayout.NORTH);
            fraDemo.getContentPane().add(butAllChange, BorderLayout.SOUTH);
            
            butAllChange.addActionListener(this);
         
            fraDemo.pack();
            fraDemo.setVisible(true);
         }


         public void actionPerformed(ActionEvent ae)
         {
            // When the button is clicked, create a new model and set it.
            // would expect the selected item to change to the result
            // of getSelectedItem in the model (i.e. "Three"). Instead
            // it is always set to "One".
            m_combo.setModel(new MyModel());
         }

         public static void main(String[] args)
         {
            ComboBugTest cbt = new ComboBugTest();
            
            cbt.doStuff();
         }


         class MyModel extends AbstractListModel implements ComboBoxModel
         {
            String[] items = new String[] {
               "One", "Two", "Three", "Four"
            };
            
            private Object m_selection;
            
            public MyModel()
            {
               // Initialise the selection. We would expect this to be the
               // selected item when changing the model to a new instance
               // of this class.
               m_selection = items[2];
            }
         
            public Object getSelectedItem()
            {
               return m_selection;
            }
            
            public void setSelectedItem(Object o)
            {
               m_selection = o;
               fireContentsChanged(this, -1, -1);
            }
            
            public Object getElementAt(int i)
            {
               return items[i];
            }
            
            public int getSize()
            {
               return items.length;
            }
         }

      }
      (Review ID: 85230)
      ======================================================================

      Name: krT82822 Date: 09/11/99


      In the following code, setting the JComboBox model causes the
      selected item on the model to change. The JComboBox should be
      *getting* the selected item from the model, not resetting it.

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

      public class BrokeCombo extends JFrame {
        public BrokeCombo() {
          JComboBox box = new JComboBox();
          this.getContentPane().add(box);
          box.setModel(new BasicModel());
        }

        private static final class BasicModel implements ComboBoxModel {
          private Vector listeners;
          private Integer selectedItem;
          
          public BasicModel() {
            listeners = new Vector();
            selectedItem = new Integer(3);
          }

          public int getSize() {
            return 5;
          }

          public Object getElementAt(int index) {
            return new Integer(index);
          }

          public void addListDataListener(ListDataListener l) {
            listeners.addElement(l);
          }

          public void removeListDataListener(ListDataListener l) {
            listeners.removeElement(l);
          }

          public Object getSelectedItem() {
            System.out.println("get: " + selectedItem);
            return selectedItem;
          }

          public void setSelectedItem(Object o) {
            System.out.println("set: " + o);
            selectedItem = (Integer) o;
            for (Enumeration enum = listeners.elements(); enum.hasMoreElements(); ) {
              ListDataListener listener = (ListDataListener) enum.nextElement();
              listener.contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, -1, -1));
            }
          }
        }

        public static final void main(String[] args) throws Exception {
          BrokeCombo frame = new BrokeCombo();
          frame.setSize(50, 50);
          frame.setVisible(true);
        }
      }
      (Review ID: 95136)
      ======================================================================

      Attachments

        Activity

          People

            mdavidsosunw Mark Davidson (Inactive)
            kryansunw Kevin Ryan (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: