JDK-4546487 : Disabled Icons don't change on JMenuItems if Action is changed
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.4.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2001-12-04
  • Updated: 2002-10-21
  • Resolved: 2002-10-21
Related Reports
Duplicate :  
Description

Name: rmT116609			Date: 12/04/2001


java version "1.3.1_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_01)
Java HotSpot(TM) Client VM (build 1.3.1_01, mixed mode)

1. Create two Actions with different Icons and set both to disabled.
2. Add one of them to a JMenuItem
3. let the (disabled) JMenuItem display
4. add the other Action to the JMenuItem
5. look again at the JMenuItem -> the Icon has not changed

The Icon *does* change, iff the Actions are enabled, so it looks like a
caching-problem of disabled Icons.

The problem is also reproducible with JDK1.4.0-beta3.

Sample sourcecode:

-------- cut here -------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class IconBug extends JFrame {

    /** Creates a new instance of IconBug */
    public IconBug() {
        setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        
        Container c = getContentPane();
        c.setLayout( new FlowLayout() );
        
        JMenu jm = new JMenu( "Menu" );
        final JMenuItem jmi = new JMenuItem( "Action" );
        jm.add( jmi );
        
        JMenuBar jmb = new JMenuBar();
        jmb.add( jm );
        
        setJMenuBar( jmb );
        
        final Action a1 = new AbstractAction() {
            public void actionPerformed( ActionEvent ae ) {}
        };
        a1.putValue( Action.SMALL_ICON, new ImageIcon(getClass().getResource( "duke4.gif"  ) ) );
        
        final Action a2 = new AbstractAction() {
            public void actionPerformed( ActionEvent ae ) {}
        };
        a2.putValue( Action.SMALL_ICON, new ImageIcon(getClass().getResource("T2.gif"  ) ) );
        
        JButton jb = new JButton( "Action 1" );
        jb.addActionListener( new ActionListener() {
            public void actionPerformed( ActionEvent ae ) {
                jmi.setAction( a1 );
            }
        });
        c.add( jb );
        
        jb = new JButton( "Action 2" );
        jb.addActionListener( new ActionListener() {
            public void actionPerformed( ActionEvent ae ) {
                jmi.setAction( a2 );
            }
        });
        c.add( jb );
        
        // set both to 'true' to see that it behaves correctly on enabled
        // Actions
        a1.setEnabled( false );
        a2.setEnabled( false );
        
        pack();
        setVisible( true );
    }

    /**
    * @param args the command line arguments
    */
    public static void main (String args[]) {
        new IconBug();
    }
}
------ cut here -----

Start the application and click on one of the buttons. Display the menu, then
click on the other button and display the menu it again -> the Icon has not
changed; the JMenuItem keeps the Icon of the first Action, regardless on what
button you click.

If you start the application again and click on the second button first, then
the JMenuItem keeps the Icon of the second Action.
(Review ID: 136742) 
======================================================================

Comments
EVALUATION Name: pzR10082 Date: 10/15/2002 If disabled icon is not set explicitly, AbstractButton.getDisabledIcon() makes a greyed icon image out of the default icon, and caches it. There are two places where we should clear the cached copy: the first is configurePropertiesFromAction(), which is called to retrieve icon from the newly set Action, the second is ButtonActionPropertyChangeListener, which is called when Action's Icon is changed. ###@###.### 2002-10-15 ======================================================================
15-10-2002

SUGGESTED FIX Name: pzR10082 Date: 10/15/2002 *** /net/diablo/export2/swing/zpm/webrev/src/share/classes/javax/swing/AbstractButton.java- Tue Oct 15 17:39:12 2002 --- AbstractButton.java Tue Oct 15 17:39:02 2002 *************** *** 1092,1097 **** --- 1092,1099 ---- setToolTipText(a!=null ? (String)a.getValue(type) : null); } else if (type.equals(Action.SMALL_ICON)) { setIcon(a!=null ? (Icon)a.getValue(type) : null); + // 4546487: also clear cached disabled icon + setDisabledIcon(null); } else if (type.equals(Action.ACTION_COMMAND_KEY)) { setActionCommand(a!=null? (String)a.getValue(type) : null); } else if (type.equals("enabled")) { *************** *** 1153,1158 **** --- 1155,1162 ---- } else if (e.getPropertyName().equals(Action.SMALL_ICON)) { Icon icon = (Icon) e.getNewValue(); button.setIcon(icon); + // 4546487: also clear cached disabled icon + button.setDisabledIcon(null); button.invalidate(); button.repaint(); } else if (e.getPropertyName().equals(Action.MNEMONIC_KEY)) { ###@###.### 2002-10-15 ======================================================================
15-10-2002