JDK-6379094 : REGRESSION: JButtons on JToolBar Violate to XP Platform Conventions
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2006-01-31
  • Updated: 2011-02-16
  • Resolved: 2006-01-31
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.6.0-rc"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.6.0-rc-b69)
Java HotSpot(TM) Client VM (build 1.6.0-rc-b69, mixed mode, sharing)


ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]


A DESCRIPTION OF THE PROBLEM :
When I add JButtons to a JToolBar using the Windows Look-and-Feel, they no
longer conform to the Windows platform conventions, and they look terrible.
On Windows, Toolbar buttons are typically square buttons with 16-pixel
icons, and have no space between them. JDK 1.5 gets this look down very
well. But in JDK 1.6, the buttons appear with wasted space on each side.
While there are very good reasons to put in that extra space in other
situations, it's all wrong for a tool bar on the Windows platform and
other platform. (I have only tested this under Windows XP.)
While the workaround is relatively simple, Mustang will force a lot of
people to go digging for a workaround when they shoudln't need to. The
workaround may also end up being platform-specific, which we really don't
want to add to our "portable" code. Also, the workaround uses the
setMargins() call, which is a relatively little-known method, and it will
take some hunting to find it. Those who don't will be forced to invent
some other hack to fix this, which they shouldn't need to do. The last
thing we Swing developers need is new reasons to write more hacks!

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the included test program under both JDK 1.5 and 1.6 and compare
the resulting screens.


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
  Tool Bar Buttons, especially the ones that only have an icon, should be
packed closely together.

ACTUAL -
Under JDK 1.5, they are packed closely together. Under 1.6, except for
the last three buttons, there's a wide space on each side that doesn't
belong. (The last three buttons incorporate the workaround.)

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;

public class MustangButtonBug extends JPanel {
	public static void main(String[] args) {
		//noinspection CatchGenericClass
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (Exception e) { }
		JFrame mainFrame = new JFrame("MustangButtonBug");
		mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		mainFrame.add(new MustangButtonBug());
		mainFrame.setBounds(10, 10, 600, 125);
		mainFrame.setVisible(true);
	}

	Icon xIcon = new XIcon();
	public MustangButtonBug() {
		super(new BorderLayout());
		JToolBar toolbar = new JToolBar();
		System.err.println("Margin = " + toolbar.getMargin());
		System.err.println("Java version = " + System.getProperty("java.version"));
		add(toolbar, BorderLayout.NORTH);
		for (int ii = 0; ii < 3; ++ii) {
			addButton(toolbar, ii);
		}
		toolbar.addSeparator();
		for (int ii=3; ii<6; ++ii)
			toolbar.add(makeAction(ii));
		
		// These buttons incorporate the workaround.
		toolbar.addSeparator();
		for (int ii=6; ii<9; ++ii)
		{
			Action tbAction = makeAction(ii);
			JButton btn = toolbar.add(tbAction);
			btn.setMargin(new Insets(0, 0, 0, 0));
		}
	}
	
	private Action makeAction(int ii) {
		Action btnAction = new AbstractAction() {
			public void actionPerformed(ActionEvent e) {
				AbstractButton btn = (AbstractButton) e.getSource();
				System.err.println("Button margin = " + btn.getMargin());
			}
		};
		btnAction.putValue(Action.SMALL_ICON, xIcon);
		btnAction.putValue(Action.NAME, "Button " + ii);
		return btnAction;
	}
	
	private void addButton(JToolBar toolbar, int ii) {
		JButton btn = new JButton("Button " + ii);
		btn.setIcon(xIcon);
		toolbar.add(btn);
	}
	
	private class XIcon implements Icon {
		public void paintIcon(Component c, Graphics g, int x, int y) {
			g.setColor(Color.black);
			int x1 = x+2;
			int x2 = x+13;
			int y1 = y+2;
			int y2 = y+13;
			g.drawLine(x1, y1, x2, y2);
			g.drawLine(x1, y2, x2, y1);
		}

		public int getIconWidth() { return 16; }
		public int getIconHeight() { return 16; }
	}
}

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

CUSTOMER SUBMITTED WORKAROUND :
Set the margins of the toolbar buttons to new Insets(0,0,0,0); (This
Insets instance may be shared among all buttons.) If you add an action
to the tool bar, the add(Action) method returns the JButton, so you
can add put the call to setMargins() there.

Release Regression From : 5.0u6
The above release value was the last known release where this 
bug was known to work. Since then there has been a regression.

Comments
EVALUATION Duplicate of 6349010. Work is in progress.
31-01-2006