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

JComboBox sometimes fails to fire ItemEvent after model change

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P4 P4
    • 1.4.0
    • 1.2.2
    • client-libs
    • beta
    • generic
    • generic



      Name: jk109818 Date: 06/26/2000


      2nd submission
      --------------------------------------------------------------------------------------------------------------


      -----Urspr?ngliche Nachricht-----
      Von: Rennecke, Fa. GFT, IMPULS, B
      Gesendet am: Montag, 26. Juni 2000 11:29
      An: 'Jeffrey Kim'
      Cc: Herzog, ITS Fil E420, B
      Betreff: AW: (Review ID: 103597) JComboBox sometimes fails to fire
      ItemEvent after model change

      Hi,

      thank you for your evaluation of our bug report. It seems that I have been
      unclear about the precise situation in which the problem occurs.

      I totally agree with you in that 4148288 and 4135029 describe pretty much
      the same attempt at using the JComboBox as a Command control which it isn't.
      But this is not the case here.

      The cause of the problem I am trying to describe is, that the JComboBox as
      well as the ListModel remember the last selected item. These get ALWAYS out
      of sync when one sets a new model.

      Result of that inconsistency is that model and view show different states in
      some situations:

      1. Initialization defaults to first item => firt selected in both
      2. Selecting second item => second selected in both
      3. Setting new model => first selected in model, old second selected in view
         here is the bug: getSelectedItem now gives the first item, but selecting
      the second item does not fire an event.

      I have provided a slightly extended code sample with this email. It shows
      the current result of getSelectedItem as well as the last item state change.
      To reproduce:

      1. Select second item (ok so far)
      2. Reset model (First selected again)
      3. Select second item again (nothing happens)

      Or, showing a more fatal case where a WRONG change event is fired:
      1. Select second item > second, fires second selected
      2. Reset model > first
      3. Select third item > third, fires SECOND deselected and third selected!

      Please note that the new model is a completely separate new instance of
      DefaultComboBoxModel. The only reason why they share the second choice as an
      instance is the fact that the VM chooses to have only one instance for
      string literals.

      This bug is still reproducible in the final 1.3 release.

      I am not doing idle observation here, the bug affects an application which
      is already in use nationwide. It affects the gender selection, which fails
      to work under certain circumstances described here. The workaround described
      solves the problem for us.

      The solution is simple: in JComboBox.setModel set selectedItemReminder to
      null to maintain consistency.

      Best regards,
      /Klaus Rennecke.


      import java.awt.BorderLayout;
      import java.awt.GridLayout;
      import javax.swing.*;
      import javax.swing.border.TitledBorder;

      /*
       * Steps to reproduce (most obvious version):
       * 1. Select the "Second Choice"
       * 2. Reset the model
       * 3. Try to select the "Second Choice" again.
       */
      public class JComboBoxBug extends JFrame
      implements java.awt.event.ActionListener, java.awt.event.ItemListener
      {
      JComboBox input;
      JLabel selected;
      JTextArea output;

      public JComboBoxBug()
      {
      addWindowListener (new java.awt.event.WindowAdapter() {
      public void windowClosing (java.awt.event.WindowEvent ev)
      { ev.getWindow().dispose(); }
      public void windowClosed (java.awt.event.WindowEvent ev)
      { System.exit (0); }
      });

      output = new JTextArea();
      output.setBorder (new TitledBorder ("output"));
      output.setEditable (false);
      getContentPane().add (BorderLayout.CENTER,
      new JScrollPane (output));

      JPanel p = new JPanel();
      p.setLayout (new GridLayout (1, 0));
      input = new JComboBox();
      input.setBorder (new TitledBorder ("input"));
      input.addItemListener (this);
      p.add (input);

      JButton reset = new JButton("Reset Model");
      reset.addActionListener (this);
      p.add (reset);

      getContentPane().add (BorderLayout.SOUTH, p);

      resetModel();
      }

      protected void message (String str)
      {
      output.append (str);
      output.append ("\n");
      }

      public void resetModel()
      {
      String data[] = {
      "First Choice", "Second Choice", "Third Choice"
      };

      input.setModel (new DefaultComboBoxModel (data));
      // Workaround: reset the selected item
      // Object item = input.getSelectedItem();
      // input.setSelectedItem (null); // Else the model would not fire
      // input.setSelectedItem (item);

      message ("getSelectedItem => "+input.getSelectedItem());
      }

      public void actionPerformed (java.awt.event.ActionEvent ev)
      {
      resetModel();
      }

      public void itemStateChanged (java.awt.event.ItemEvent ev)
      {
      message ("itemStateChanged <= "+ev.getItem()+" "+ch(ev));
      message ("getSelectedItem => "+input.getSelectedItem());
      }

      private String ch (java.awt.event.ItemEvent ev)
      {
      switch (ev.getStateChange())
      {
      case ev.SELECTED: return "SELECTED";
      case ev.DESELECTED: return "DESELECTED";
      default:
      return "UNKNOWN: "+ev.getStateChange();
      }
      }

      public static void main (String args[])
      {
      JComboBoxBug bug = new JComboBoxBug();
      bug.pack();
      bug.show();
      }
      }






      1st submission
      ------------------------------------------------------------------------------------------------------------


      java version "1.2.2"
      Classic VM (build JDK-1.2.2-001, native threads, symcjit)
      java version "1.2"
      Classic VM (build Linux_JDK_1.2_pre-release-v2, native threads, sunwjit)


      The JCheckBox does not fire an ItemEvent for user input selecting a choice
      which is identical to a choice which was selected with a previous model. That
      might seem to be an obscure chain of actions but is in fact quite common.

      This is because the JComboBox remembers the selected item in the field
      'selectedItemReminder' and does not maintain that field when the model is
      changed.

      ==========
      import javax.swing.*;

      /*
       * Steps to reproduce (most obvious version):
       * 1. Select the "Second Choice"
       * 2. Reset the model
       * 3. Try to select the "Second Choice" again.
       */
      public class JComboBoxBug extends JFrame
      implements java.awt.event.ActionListener, java.awt.event.ItemListener
      {
      JComboBox input;
      JLabel output;

      public JComboBoxBug()
      {
      getContentPane().setLayout (new java.awt.GridLayout (0, 1));

      addWindowListener (new java.awt.event.WindowAdapter() {
      public void windowClosing
      (java.awt.event.WindowEvent ev)
      { ev.getWindow().dispose(); }
      public void windowClosed
      (java.awt.event.WindowEvent ev)
      { System.exit (0); }
      });

      input = new JComboBox();
      input.addItemListener (this);
      getContentPane().add (input);

      output = new JLabel();
      getContentPane().add (output);

      JButton reset = new JButton("Reset Model");
      reset.addActionListener (this);
      getContentPane().add (reset);

      resetModel();
      }

      public void resetModel()
      {
      output.setText ("[not initialized]");

      String data[] = { "First Choice", "Second Choice" };
      input.setModel (new DefaultComboBoxModel (data));
      // Workaround: reset the selected item
      // Object item = input.getSelectedItem();
      // input.setSelectedItem (null); // Else the model would not
      fire
      // input.setSelectedItem (item);
      }

      public void actionPerformed (java.awt.event.ActionEvent ev)
      {
      resetModel();
      }

      public void itemStateChanged (java.awt.event.ItemEvent ev)
      {
      output.setText (ev.getItem().toString());
      }

      public static void main (String args[])
      {
      JComboBoxBug bug = new JComboBoxBug();
      bug.pack();
      bug.show();
      }
      }
      (Review ID: 103597)
      ======================================================================

            mdavidsosunw Mark Davidson (Inactive)
            jkimsunw Jeffrey Kim (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: