JDK-4898630 : JColorChooser - added chooser panels lost on updateComponentTreeUI
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.3.1,1.4.1,1.4.2,5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • OS: windows_nt,windows_2000,windows_xp
  • CPU: x86
  • Submitted: 2003-07-30
  • Updated: 2014-03-13
  • Resolved: 2014-03-13
Related Reports
Duplicate :  
Relates :  
Description
Name: jk109818			Date: 07/30/2003


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

Also occurs on 1.3.

FULL OS VERSION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
If you use SwingUtilities.updateComponentTreeUI(Component c) to update a JColorChooser which has color chooser panels added to it, these added panels are lost, reverting to the default chooser panels.
This problem is even worse if the default panels are replaced with new chooser panels.  If the SwingUtilities.updateComponentTreeUI(Component c) is used after JColorChooser.setColorChooserPanels(), an IllegalArgumentException is thrown.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run both examples provided and observe the behavior.
Comment out the SwingUtilities.updateComponentTreeUI(frame); line from both examples.
Run the examples again, and observe the proper behavior.

EXPECTED VERSUS ACTUAL BEHAVIOR :
Both runs should work exactly the same with the updateComponentTreeUI call inserted and removed.
With ColorChooserBug1, the added panel does not show up after updateComponentTreeUI.
With ColorChooserBug2, an IllegalArgumentException is thrown.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
The following exception is thrown when running ColorChooserBug2:

java.lang.IllegalArgumentException: chooser panel not in this chooser
	at javax.swing.JColorChooser.removeChooserPanel(JColorChooser.java:409)
	at javax.swing.plaf.basic.BasicColorChooserUI.uninstallDefaultChoosers(BasicColorChooserUI.java:61)
	at javax.swing.plaf.basic.BasicColorChooserUI.uninstallUI(BasicColorChooserUI.java:108)
	at javax.swing.JComponent.setUI(JComponent.java:444)
	at javax.swing.JColorChooser.setUI(JColorChooser.java:209)
	at javax.swing.JColorChooser.updateUI(JColorChooser.java:220)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1100)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1111)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1111)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1111)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1111)
	at javax.swing.SwingUtilities.updateComponentTreeUI(SwingUtilities.java:1092)
	at ColorChooserBug2.main(ColorChooserBug2.java:28)
Exception in thread "main"

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import javax.swing.*;
import javax.swing.colorchooser.AbstractColorChooserPanel;
public class ColorChooserBug1 {
	public static void main(String[] args) {
		JFrame frame = new JFrame("Test");
		JColorChooser cc = new JColorChooser();
		cc.addChooserPanel(new AbstractColorChooserPanel() {
			public void updateChooser() {
			}
			protected void buildChooser() {
				this.add(new JLabel("This is an added panel"));
			}
			public String getDisplayName() {
				return "Added Tab";
			}
			public Icon getSmallDisplayIcon() {
				return null;
			}
			public Icon getLargeDisplayIcon() {
				return null;
			}
		});
		frame.getContentPane().add(cc);
		
		// Add & Remove the following line to see the bug in action
		SwingUtilities.updateComponentTreeUI(frame);
		
		frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		frame.pack();
		frame.show();
	}
}
=============================================================
import javax.swing.*;
import javax.swing.colorchooser.AbstractColorChooserPanel;
public class ColorChooserBug2 {
	public static void main(String[] args) {
		JFrame frame = new JFrame("Test");
		JColorChooser cc = new JColorChooser();
		cc.setChooserPanels(new AbstractColorChooserPanel[] {
			new AbstractColorChooserPanel() {
				public void updateChooser() {
				}
				protected void buildChooser() {
					this.add(new JLabel("This is an added panel"));
				}
				public String getDisplayName() {
					return "Added Tab";
				}
				public Icon getSmallDisplayIcon() {
					return null;
				}
				public Icon getLargeDisplayIcon() {
					return null;
				}
			}
		});
		frame.getContentPane().add(cc);
		
		// Add & Remove the following line to see the bug in action
		SwingUtilities.updateComponentTreeUI(frame);
		
		frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		frame.pack();
		frame.show();
	}
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
1. Add additional chooser panels back after every updateComponentTreeUI call.
2. Avoid changing L&Fs with added chooser panels on JColorChooser.
(Incident Review ID: 182792) 
======================================================================

Comments
EVALUATION Name: keR10081 Date: 08/01/2003 While we shouldn't see the exception (which is addressed in bug 4711996 and would be fixed for 1.5.0), handling added and removed panels during updating ui is sort of tricky. Only obvious ways which can be reasonable are: 1. Reconstruct only default panels and let user handle ui updates to add custom panels. 2. Reconstruct default panels and add custom panels ourselves, but that would require API change and still leave some problems. ###@###.### ====================================================================== Name: keR10081 Date: 08/11/2003 See suggested fix for details ###@###.### ======================================================================
25-09-2004

SUGGESTED FIX Name: keR10081 Date: 08/11/2003 ------- BasicColorChooserUI.java ------- *** /tmp/sccs.4EaizH ?? ??? 11 18:55:15 2003 --- BasicColorChooserUI.java ?? ??? 11 18:55:14 2003 *************** *** 64,71 **** } protected void uninstallDefaultChoosers() { ! for( int i = 0 ; i < defaultChoosers.length; i++) { ! chooser.removeChooserPanel( defaultChoosers[i] ); } } --- 64,76 ---- } protected void uninstallDefaultChoosers() { ! AbstractColorChooserPanel[] choosers = chooser.getChooserPanels(); ! for( int i = 0 ; i < choosers.length; i++) { ! for( int j = 0 ; j < defaultChoosers.length; j++) { ! if (choosers[i] == defaultChoosers[j]) { ! chooser.removeChooserPanel( choosers[i] ); ! } ! } } } *************** *** 84,93 **** chooser.setLayout( new BorderLayout() ); defaultChoosers = createDefaultChoosers(); ! chooser.setChooserPanels(defaultChoosers); ! previewPanelHolder = new JPanel(new CenterLayout()); previewPanelHolder.setName("ColorChooser.previewPanelHolder"); if (DefaultLookup.getBoolean(chooser, this, --- 89,102 ---- chooser.setLayout( new BorderLayout() ); + AbstractColorChooserPanel[] choosers = chooser.getChooserPanels(); defaultChoosers = createDefaultChoosers(); ! chooser.setChooserPanels(defaultChoosers); ! for( int i = 0 ; i < choosers.length; i++) { ! chooser.addChooserPanel(choosers[i]); ! } ! previewPanelHolder = new JPanel(new CenterLayout()); previewPanelHolder.setName("ColorChooser.previewPanelHolder"); if (DefaultLookup.getBoolean(chooser, this, *************** *** 96,102 **** "ColorChooser.previewText", chooser.getLocale()); previewPanelHolder.setBorder(new TitledBorder(previewString)); } ! chooser.add(previewPanelHolder, BorderLayout.SOUTH); installPreviewPanel(); chooser.applyComponentOrientation(c.getComponentOrientation()); --- 105,111 ---- "ColorChooser.previewText", chooser.getLocale()); previewPanelHolder.setBorder(new TitledBorder(previewString)); } ! chooser.add(previewPanelHolder, BorderLayout.SOUTH); installPreviewPanel(); chooser.applyComponentOrientation(c.getComponentOrientation()); *************** *** 312,318 **** super("color"); } } ! } --- 321,327 ---- super("color"); } } ! } ======================================================================
25-09-2004