JDK-4848910 : UIManager only updates colors once
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.4.1
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2003-04-15
  • Updated: 2003-04-15
  • Resolved: 2003-04-15
Description

Name: jk109818			Date: 04/15/2003


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

FULL OPERATING SYSTEM VERSION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
The following code works but only once.

UIManager.put( "Button.background", Color.black );
SwingUtilities.updateComponentTreeUI( this.getContentPane
() );

If I try to make the same call with a new color, the
button color will remain black and will not change.

It seems like this should not be the case.  Why only
update the colors once.  I want to provide my users to
change the colors dynamically without having to call
setBackground for every control I have.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1.Make simple JFrame based application.
2.Create two buttons.
3.In the callback to the first button add this code:
UIManager.put( "Button.background", Color.black );
SwingUtilities.updateComponentTreeUI( this.getContentPane
() );
4.In the callback to the second button, add this code:
UIManager.put( "Button.background", Color.green);
SwingUtilities.updateComponentTreeUI( this.getContentPane
() );
5. Compile the program.  Push one of the buttons.  You
will notice the color change according to the button you
pressed.
6. Push the other button.  The color will not change.  Why?

EXPECTED VERSUS ACTUAL BEHAVIOR :
I expected that when I pushed the button associated with
the color black, the button background color would become
black.  Then, when I pushed the button associated with the
color green, I expected the button background color would
become green. But it obviously did not.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
There were not error messages.  It just does not function as I expect.  No
documentation suggest that I have found suggests it should only work once.
And, if it does.  Why???

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
( 2 short files.)

***Begin File ColorTest.java***

package ColorTest;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.UIManager;
import java.awt.Dimension;
import java.awt.Toolkit;

public class ColorTest
{
    public ColorTest()
    {
        Frame frame = new ColorTestFrm();
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        Dimension frameSize = frame.getSize();
        if (frameSize.height > screenSize.height)
        {
            frameSize.height = screenSize.height;
        }
        if (frameSize.width > screenSize.width)
        {
            frameSize.width = screenSize.width;
        }
        frame.setLocation((screenSize.width - frameSize.width) / 2,
(screenSize.height - frameSize.height) / 2);
        frame.addWindowListener(new WindowAdapter()
            {
                public void windowClosing(WindowEvent e)
                {
                    System.exit(0);
                }
            });
        frame.setVisible(true);
    }

    public static void main(String[] args)
    {
        try
        {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName
());
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }

        new ColorTest();
    }
}

***End File ColorTest.java***

***Begin File ColorTestFrm.java***
package ColorTest;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
import java.awt.Rectangle;
import javax.swing.JRadioButton;
import javax.swing.JComboBox;
import java.awt.Dimension;


public class ColorTestFrm extends JFrame
{
    private JButton m_changeColor1      = new JButton();;
    private JButton m_changeColor2      = new JButton();

    public ColorTestFrm()
    {
        try
        {
            jbInit();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }

    }

    private void jbInit() throws Exception
    {


        this.getContentPane().setLayout(null);
        this.setSize(new Dimension(212, 167));
        m_changeColor1.setText("Change Color Black");
        m_changeColor1.setBounds(new Rectangle(10, 15, 180, 40));
        //m_changeColor1.setBackground( Color.RED );
        m_changeColor1.addActionListener(new ActionListener()
            {
                public void actionPerformed(ActionEvent e)
                {
                    ColorChangeButtonClicked();
                }
            });
        m_changeColor2.setText("Change Color Green");
        m_changeColor2.setBounds(new Rectangle(10, 75, 180, 40));
        m_changeColor2.addActionListener(new ActionListener()
            {
                public void actionPerformed(ActionEvent e)
                {
                    ColorChangeButton2Clicked();
                }
            });
        this.getContentPane().add(m_changeColor2, null);
        this.getContentPane().add(m_changeColor1, null);
    }

    private void ColorChangeButtonClicked()
    {
        UIManager.put( "Button.background", Color.black );
        SwingUtilities.updateComponentTreeUI( this.getContentPane() );
    }

    private void ColorChangeButton2Clicked()
    {
        UIManager.put( "Button.background", Color.green );
        SwingUtilities.updateComponentTreeUI( this.getContentPane() );
    }
}

***End File ColorTestFrm.java***

---------- END SOURCE ----------

CUSTOMER WORKAROUND :
No known work around.
(Review ID: 181248) 
======================================================================

Comments
EVALUATION The ComponentUI classes will only reset the colors if they detect the developer hasn't set them. Detection is done by looking at the current color, if it implements UIResource, it is assumed the developer didn't set it. Because your code is setting a color that is not a UIResource, we assume the developer set the color, and therefor we don't reset it when you subsequently change the property. If you instead use ColorUIResource, you can update the color as many times as you like. ###@###.### 2003-04-15
15-04-2003