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

Toolbar button borders missing in Metal LAF

    XMLWordPrintable

    Details

      Description

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

      Also occurs on Mustang Beta:

      java version "1.6.0-beta"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.6.0-beta-b59g)
      Java HotSpot(TM) Client VM (build 1.6.0-beta-b59g, mixed mode, sharing)

      ADDITIONAL OS VERSION INFORMATION :
      This bug happens on Windows XP and (very likely) any other version of Windows in which you can use the Windows Look-And-Feel (LAF).

      A DESCRIPTION OF THE PROBLEM :
      If you switch from the Metal LAF to the Windows LAF, then create a JFileChooser, and then switch back to Metal, from that point on any new toolbars will be missing their borders on their buttons!

      (The part about displaying a filechooser is just *my* way of making this happen. I'm sure there is a more elegant way to reproduce this bug.)

      I strongly suspect that this bug is related to bug #4856008.

      It may also be a regression of bug #4781912.


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Compile and run the source code that I've provided, on Windows. A little window will pop up. Notice the two toolbar buttons in the window. They don't do anything, but they look all nice and good--you can roll your mouse over them to see their borders in more detail.

      Now click on the button in the frame (the one marked "Spawn new Frame".)

      When you do, the LAF will change from Metal to Windows, and a hidden JFileChooser will be created and then thrown away. The LAF will then change back to Metal, and a copy of the window will appear, so that now you have two windows, both themed with the Metal LAF. (You will never actually see the LAF change on screen, though. Look in the source code to see when it's actually happening.)

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The newly spawned window should look exactly like the original window; after all, they were created using the same code and are both themed using the same LAF.
      ACTUAL -
      That hidden Windows-themed JFileChooser broke part of the Metal LAF!

      The toolbar buttons in the second window have the wrong borders now--instead of a MetalBorders$ButtonBorder and a MetalBorders$RolloverMarginBorder, they have an EmptyBorder, and it looks quite wrong.

        From this point onward, anytime you create a new ToolBar with buttons, the buttons will exhibit this border problem.

      If you comment out the hidden JFileChooser part of my source code, then this bug goes away.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.awt.*;
      import java.awt.event.ActionEvent;
      import java.awt.event.ActionListener;
      import java.awt.image.BufferedImage;

      import javax.swing.*;
      import javax.swing.border.Border;


      public class BadButton {

         public static void main( String [] args ) throws Throwable {
            spawnNewFrame();
         }
         
         private static void spawnNewFrame() {
            // create frame with toolbar
            JFrame frame = new JFrame();
            frame.setVisible(true);
            JToolBar toolbar = new JToolBar();
            frame.getContentPane().setLayout( new BorderLayout() );
            frame.add(toolbar, BorderLayout.NORTH );

            // add laf-changer buttons to toolbar
            Action dotBlueAction = new DotAction(Color.BLUE);
            Action dotRedAction = new DotAction(Color.RED);
            toolbar.add( dotBlueAction );
            Border border = toolbar.add( dotRedAction ).getBorder();
            
            // this println gives a clue to the problem
            // border SHOULD be a compound border containing a
            // MetalBorders$ButtonBorder
            // and a MetalBorders$RolloverMarginBorder (as returned by
            // UIManager.getBorder( "ToolBar.rolloverBorder" ), but once the bug
            // has occurred, you end up geting an EmptyBorder instead
            System.out.println( border.getClass() );

            // add a button for spawning a new frame
            JButton spawnButton = new JButton("Spawn new Frame");
            spawnButton.addActionListener( new ActionListener() {
               public void actionPerformed( ActionEvent e ) {
                  try {
                     // remove the next 4 statements, and the bug goes away!
                     UIManager.setLookAndFeel(
                        "com.sun.java.swing.plaf.windows.WindowsLookAndFeel" );
                     JFileChooser chooser = new JFileChooser();
                     SwingUtilities.updateComponentTreeUI( chooser );
                     UIManager.setLookAndFeel(
                        "javax.swing.plaf.metal.MetalLookAndFeel" );
                     
                     spawnNewFrame();
                  } catch (Throwable t) {
                     System.out.println(t);
                  }
               }
            });
            
            frame.add(spawnButton, BorderLayout.SOUTH);
            frame.pack();
            
         }
         
         // A simple action that creates a button with colored dot for an icon.
         static class DotAction extends AbstractAction {
            
            DotAction( Color color ) {
               BufferedImage bimage =
                  new BufferedImage(20,20, BufferedImage.TYPE_4BYTE_ABGR);
               Graphics2D g2d = bimage.createGraphics();
               g2d.setColor( color );
               g2d.fillOval( 0,0,20,20 );
               ImageIcon icon = new ImageIcon(bimage);
               putValue( Action.SMALL_ICON, icon );
            };
            
            public void actionPerformed( ActionEvent e ) {
               // do nothing
            }
         };
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      You can work around this problem by manually setting the border for each toolbar button after it is created:

         JButton button = toolbar.add( action );
         if ( UIManager.getLookAndFeel().getID().equals("Metal") ) {
            Border properBorder = UIManager.getBorder( "ToolBar.rolloverBorder" );
            button.setBorder( properBorder );
         }

        Attachments

          Activity

            People

            Assignee:
            Unassigned Unassigned
            Reporter:
            rmandalasunw Ranjith Mandala (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Dates

              Created:
              Updated:
              Imported:
              Indexed: