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

JRadioMenuButtonMenuItem Incorrectly Colors Text After paintIcon(...) is Invoked

    XMLWordPrintable

Details

    Description

      Name: gm110360 Date: 07/28/2004


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

      ADDITIONAL OS VERSION INFORMATION :
      Linux hqwks10966.solipsys.com 2.4.20-31.9 #1 Tue Apr 13 18:04:23 EDT 2004 i686 i686 i386 GNU/Linux

      A DESCRIPTION OF THE PROBLEM :
      I have stumbled across what appears to be a small bug in Java's Look & Feel implementation. Probably in the UI delegate BasicRadioMenuButtonUI, but I haven't looked that far into it. The problem is that when I paint the contents of an Icon, and do not restore the original state of the supplied graphics context, the last paint color used in the icon's paintIcon(...) method becomes the foreground color for the text in the JRadioButtonMenuItem.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Here's how to...

      - Build the sample code: javac LookAndFeelBug.java
      - Execute the sample application: java LookAndFeelBug

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      I would expect the foreground of the text in the JRadioButtonMenuItems to be consistent with the rest of the text foreground colors in all of the other menu items.
      ACTUAL -
      The text foreground color in the JRadioButtonMenuItems is the same as the last color used to paint in the Icon's paintIcon(...) method. There is a bug related to this issue that supports my belief that the code responsible for painting the text in the JRadioButtonMenuItem should not be expecting the state of the Graphics object to already have the correct color setting, see bug #4886533. [Sun: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4886533]

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.awt.Color;
      import java.awt.Component;
      import java.awt.Graphics;
      import java.awt.Graphics2D;
      import java.awt.event.ActionEvent;
      import java.awt.event.ActionListener;
      import java.awt.event.KeyEvent;

      import java.lang.reflect.Constructor;
      import java.lang.reflect.InvocationTargetException;

      import javax.swing.ButtonGroup;
      import javax.swing.Icon;
      import javax.swing.JFrame;
      import javax.swing.JMenu;
      import javax.swing.JMenuBar;
      import javax.swing.JMenuItem;
      import javax.swing.JRadioButtonMenuItem;
      import javax.swing.JSeparator;

      /**
       * This class displays a possible Look & Feel realted bug that allows the
       * last color used to paint an <code>Icon</code> to override the foreground
       * color of the text in a <code>JRadioButtonMenuItem</code>.
       *
       * Also, a bug report in Sun's own bug database suggests that the BadIcon
       * implementation should be correct is here:
       *
       * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4886533
       **/
      public class LookAndFeelBug
      {

        /**
         * Base class for sample icon implementations.
         **/
        protected static abstract class AbstractIcon
          implements Icon
        {

          protected static final int SIZE = 16;

          protected Color color;

          public AbstractIcon( Color color )
          {
            this.color = color;
          }

          public int getIconWidth()
          {
            return SIZE;
          }

          public int getIconHeight()
          {
            return SIZE;
          }
        }

        /**
         * An icon that behaves properly.
         **/
        protected static class GoodIcon
          extends AbstractIcon
        {

          public GoodIcon( Color color )
          {
            super( color );
          }

          public void paintIcon( Component c, Graphics g, int x, int y )
          {
            Color originalColor = g.getColor();
            g.setColor( color );
            g.fill3DRect( x, y, SIZE, SIZE, true );
            g.setColor( originalColor );
          }
        }

        /**
         * An icon that misbehaves and causes its color to override the menu
         * item's text color.
         **/
        protected static class BadIcon
          extends AbstractIcon
        {

          public BadIcon( Color color )
          {
            super( color );
          }

          /**
           * The offending code, should the BadIcon class be responsible for
           * restoring the state of the supplied graphics context after it is
           * done drawing the contents of the icon?
           **/
          public void paintIcon( Component c, Graphics g, int x, int y )
          {
            g.setColor( color );
            g.fill3DRect( x, y, SIZE, SIZE, true );
          }
        }

        /**
         * Return a menu that contains several radio button menu items.
         **/
        public static JMenu createSubMenu( String text, Class iconImpl )
          throws NoSuchMethodException,
                 InstantiationException,
                 IllegalAccessException,
                 InvocationTargetException
        {
          JMenu menu = new JMenu( text );

          ButtonGroup group = new ButtonGroup();

          Class[] colorArg = new Class[] { Color.class };
          Constructor iconInit = iconImpl.getConstructor( colorArg );

          Object[] redArg = new Object[] { Color.RED };
          Icon redIcon = (Icon) iconInit.newInstance( redArg );
          JRadioButtonMenuItem red = new JRadioButtonMenuItem( "Red", redIcon );
          red.setSelected( true );
          group.add( red );
          menu.add( red );

          Object[] greenArg = new Object[] { Color.GREEN };
          Icon greenIcon = (Icon) iconInit.newInstance( greenArg );
          JRadioButtonMenuItem green = new JRadioButtonMenuItem( "Green", greenIcon );
          group.add( green );
          menu.add( green );

          Object[] blueArg = new Object[] { Color.BLUE };
          Icon blueIcon = (Icon) iconInit.newInstance( blueArg );
          JRadioButtonMenuItem blue = new JRadioButtonMenuItem( "Blue", blueIcon );
          group.add( blue );
          menu.add( blue );

          return menu;
        }

        /**
         * Entry point for running the test application.
         **/
        public static void main( String[] args )
        {
          JFrame frm = new JFrame( LookAndFeelBug.class.getName() );
          frm.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

          JMenuBar menuBar = new JMenuBar();
          frm.setJMenuBar( menuBar );

          JMenu fileMenu = new JMenu( "File" );
          fileMenu.setMnemonic( KeyEvent.VK_F );
          menuBar.add( fileMenu );

          try
          {
            fileMenu.add( createSubMenu( "The Good", GoodIcon.class ) );
          }
          catch( Throwable t )
          {
            t.printStackTrace();
          }

          try
          {
            fileMenu.add( createSubMenu( "The Bad", BadIcon.class ) );
          }
          catch( Throwable t )
          {
            t.printStackTrace();
          }

          fileMenu.add( new JSeparator() );

          JMenuItem exit = new JMenuItem( "Exit" );
          exit.setMnemonic( KeyEvent.VK_X );
          exit.addActionListener( new ActionListener()
          {
            public void actionPerformed( ActionEvent evt )
            {
              System.exit( 0 );
            }
          } );
          fileMenu.add( exit );

          frm.setSize( 300, 200 );
          frm.setVisible( true );
        }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      By storing a copy of the original color used by the Graphics context, and then restoring it before returning from the paintIcon(...) method, the JRadioButtonMenuItems will draw correctly. See the GoodIcon class in the test case above.
      (Incident Review ID: 290225)
      ======================================================================

      Attachments

        Activity

          People

            alexp Alexander Potochkin (Inactive)
            gmanwanisunw Girish Manwani (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: