JDK-4318851 : ItemEvent not triggered List,Choice,CheckBox,CheckboxMenuItem
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.1,1.3.0
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS:
    solaris_2.5.1,solaris_10,windows_95,windows_nt solaris_2.5.1,solaris_10,windows_95,windows_nt
  • CPU: generic,x86,sparc
  • Submitted: 2000-03-04
  • Updated: 2001-11-29
  • Resolved: 2001-11-29
Related Reports
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
OS: WinNT and Solaris

ItemEvent is not triggered for List, Choice, CheckBox and CheckboxMenuItem when items are selected programmatically.

When items are selected programmatically using the respective methods like
list.select(index) , ItemEvent is not triggered.
In this sample program, clicking the respective buttons changes the selection
of items in that component programmatically. Triggering of events can be 
verified at the command prompt. Repeated clicking of the buttons will select


How to reproduce the Bug? -------->

Run this sample code. You would see a frame with a list,choice, checkbox, 
few buttons and a menu with checkbox menuitem.
Click the buttons one after other and check at the command prompt, whether 
any ItemEvent is triggered or not. If not, bug is reproduced.
NOTE: Clicking the buttons repeatedly selects a new item everytime to ensure 
that the item event is triggered everytime the button is clicked. 

Comments
EVALUATION Commit to fix in Merlin (SQE functional test). eric.hawkes@eng 2000-03-06 This "bug" has been on the books for some time: 4032466 : item events not generated when state programmaticaly set on Checkbox/List 4034837 : Checkbox.setState() does not notify listeners 4067113 : ItemListener not fired when using methods to select/deselect The documentation for the related classes is vague and even contradictory: java.awt.event.ItemListener contains a method named "itemStateChanged", which might imply an event would be received when a Component's setState() method were called. The ItemListener documentation also states that itemStateChanged() is called whan an "item-selection event occurs", though it is not made clear if this only refers to user-generated events (mouse or keyboard input), or also through setState(). java.awt.event.ItemEvent is an event which "indicates that an item was selected of deselected". Again, no clarification if these events are user-generated only, or also can be programatic. The Java Class Libraries Second Edition, Volume 2 by Chan & Lee DOES provide more detail, but only in some places. Checkbox: "A checkbox fires an item event whenever it is clicked" (p222) Choice: "A choice fires an item event whenever the user selects an item" (p252) ItemEvent: "the event is fired by a component peer in response to some user gesture" (p903) So, the first problem is that the present documentation is inadequate. The second problem is that it is not a good idea to have ItemEvents fire in reaction to a call to setState(). One reason for this is that setState() calls made inside of an ItemListener could lead to an infinite loop of ItemEvents. The following example from page 232 of The Java Class Libraries Second Edition demonstrates this (and also indicates that setState() was not expected to fire an event): This example creates a checkbox and a checkbox menu item and synchronizes their check states. If the checkbox is set to on, so is the checkbox menu item. import java.awt.*; import java.awt.event.ItemListener; import java.awt.event.ItemEvent; public class Example extends Frame implements ItemListener { CheckboxMenuItem mi = new CheckboxMenuItem("Play sound for new mail"); Checkbox cb = new Checkbox("Plaly sound for new mail"); public Example() { super("setState Example"); MenuBar mb = new MenuBar(); Menu m = new Menu("Options"); m.add(mi); mb.add(m); setMenuBar(mb); add(cb, BorderLayout.SOUTH); cb.addItemListener(this); mi.addItemListener(this); pack(); show(); } public void itemStateChanged(ItemEvent evt) { if (evt.getSource() == mi) { cb.setState(mi.getState()); <-------------- } else { mi.setState(cb.getState()); <-------------- } } static public void main(String[] args) { new Example(); } } The troublesome part, of course, is the itemStateChanged() method. If setState() were to fire an ItemEvent, it would trigger another call to itemStateChanged(), which would fire yet ANOTHER ItemEvent, ad inifinitum. It is also worth mentioning that it is standard in GUI systems for events to be sent for user actions, but NOT for programmatic changes to a GUI element's state. Consider the LB_SETCURSEL/LBN_SELCHANGE messages in the Win32 API. LB_SETCURSEL is sent to programmatically select an item from a list. LBN_SELCHANGE is sent when a list box selection is changing (presumably when a user clicks on a different item). In the remarks for LBN_SELCHANGE message, "This notification message is not sent if the LB_SETCURSEL message changes the selection." The argument in favor of changing the behavior of setState() is that listeners observing the Component in question would not be notified of programmatic changes in the Component's state. This is true, however it isn't too hard to make this work (see Work Arounds). The bottom line is that sending ItemEvents from programmatic changes to a Component state would: -break (existing and future) well-written code -make implementing present functionality of said code obtuse, if not impossible -not add any functionality not possible with the present API -be contrary to standard convetion in GUI APIs Instead, documentation for classes implementing the java.awt.ItemSelectable interface, that is: java.awt.Checkbox java.awt.Choice java.awt.List java.awt.CheckboxMenuItem java.awt.ItemSelectable java.awt.event.ItemListener java.awt.event.ItemEvent javax.swing.AbstractButton javax.swing.JComboBox will be clarified to explicitly state that ItemEvents are only fired in reaction to user-generated input events. brent.christian@eng 2000-03-16 ----------------------------------------------------------------------------- I filed 2 java documentation bugs to reflect this resolution by Brent. #4324396 & #4324406 Roger Pham 3/26/2000 --- Requested doc changes have been made. ###@###.### 2001-11-28
28-11-2001

WORK AROUND From bug 4067113: --- The workarounds are (a) accompany every call that changes the selection state with a call to the same code that the listener would invoke, or (b) subclass List with something that overrides all the selection-modifying methods to invoke the listern callback. --- brent.christian@eng 2000-03-16
16-03-2000