United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-4523149 : 1.4 REGRESSION: JButton loses border when placed inside JToolBar

Details
Type:
Bug
Submit Date:
2001-11-05
Status:
Resolved
Updated Date:
2003-04-12
Project Name:
JDK
Resolved Date:
2002-08-12
Component:
client-libs
OS:
windows_nt,solaris_7,linux,windows_2000
Sub-Component:
javax.swing
CPU:
x86,sparc
Priority:
P3
Resolution:
Fixed
Affected Versions:
1.4.0
Fixed Versions:
1.4.2 (mantis)

Related Reports
Duplicate:

Sub Tasks

Description

Name: ks88420			Date: 11/05/2001


java version "1.4.0-beta3"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-beta3-b84)
Java HotSpot(TM) Client VM (build 1.4.0-beta3-b84, mixed mode)

JButton.setBorder() has no effect when the button is placed within a JToolBar.
Run the following program with JDK1.4 beta3 to see effects.

Application1.java
=================
import javax.swing.UIManager;
import java.awt.*;

public class Application1
{
    private boolean packFrame = false;

    /**Construct the application*/
    public Application1()
    {
        Frame1 frame = new Frame1();
        //Validate frames that have preset sizes
        //Pack frames that have useful preferred size info, e.g. from their
layout
        if (packFrame)
        {
            frame.pack();
        }
        else
        {
            frame.validate();
        }
        //Center the window
        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.setVisible(true);
    }
    /**Main method*/
    public static void main(String[] args)
    {
        try
        {
            UIManager.setLookAndFeel
("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
        }
        catch(Exception e)
        {
            System.out.println("look and feel setup error");
        }
        new Application1();
    }
}


Frame1.java
===========
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

public class Frame1 extends JFrame
{
    private JPanel contentPane;
    private BorderLayout borderLayout1 = new BorderLayout();

    /**Construct the frame*/
    public Frame1()
    {
        enableEvents(AWTEvent.WINDOW_EVENT_MASK);
        try
        {
            jbInit();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
    /**Component initialization*/
    private void jbInit() throws Exception
    {
        //setIconImage(Toolkit.getDefaultToolkit().createImage
(Frame1.class.getResource("[Your Icon]")));
        contentPane = (JPanel) this.getContentPane();
        contentPane.setLayout(borderLayout1);
        this.setSize(new Dimension(400, 300));
        this.setTitle("Frame Title");

        JToolBar toolbar = new JToolBar();
        contentPane.add(toolbar,BorderLayout.NORTH);

        JButton button = new JButton("My border should be EmptyBorder");
        button.setBorder(new EmptyBorder(2,1,0,1));
        toolbar.add(button);
    }
    /**Overridden so we can exit when window is closed*/
    protected void processWindowEvent(WindowEvent e)
    {
        super.processWindowEvent(e);
        if (e.getID() == WindowEvent.WINDOW_CLOSING)
        {
            System.exit(0);
        }
    }
}
(Review ID: 134871) 
======================================================================

Name: jk109818			Date: 04/30/2002





A DESCRIPTION OF THE PROBLEM :
BasicToolBarUI.ToolBarContListener.ContainerListener.compone
ntAdd (shown below) has been changed to overwrite a child's
border when it is added to a toolbar. This was not the
behavior of previous JDK versions and it causes
difficulties for our code base. I don't understand why the
new version of the code needs to overwrite the border of a
child when it is added. If the problem stemmed from having
a child with no border---null, then I suggest that the code
be changed to check for a null border and THEN add a
border, otherwise this seems to violate the contract of the
developer setting a property---the border---and expecting
this property to not change from underneath him/her
silently. Other properties do not exhibit this behavior so
why should borders? In addition, I could find no
documentation that describes this change. If it is truly
necessary to change the border because of some other
dependency, then I suggest that you give the developer the
option to opt out of the change.

Because of the structure of our code, this change has
forced us to inefficiently save the border for a widget,
add the widget to the toolbar, and then restore the border.
Please, reconsider this change.


REGRESSION.  Last worked in version 1.3.1

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Set a border such as a bevel border (not a compound
border) on a widget, say a button.
2. Add the widget to a toolbar
3. Display the toolbar.
4. A compound border has now replaced the bevel border.

EXPECTED VERSUS ACTUAL BEHAVIOR :
The border should not be altered when a widget is added to
a toolbar.

This bug can be reproduced always.

---------- BEGIN SOURCE ----------
Under JDK1.4Beta3
BasicToolBarUI.ToolBarContListener.ContainerListener.compone
ntAdd is written as follows:

    protected class ToolBarContListener implements
ContainerListener
    {
        public void componentAdded( ContainerEvent e )	{
	    Component c = e.getChild();

	    if ( toolBarFocusListener != null ) {
	        c.addFocusListener( toolBarFocusListener );
	    }

	    if (isRolloverBorders()) {
		setBorderToRollover(c);
	    } else {
		setBorderToNonRollover(c);
	    }
	}

Under JDK1.3.1 it is written as follows:
    protected class ToolBarContListener implements
ContainerListener
    {
        public void componentAdded( ContainerEvent e )
	{
	    Component c = e.getChild();

	    if ( toolBarFocusListener != null )
	    {
	        c.addFocusListener( toolBarFocusListener );
	    }
	}

        public void componentRemoved( ContainerEvent e )
	{
	    Component c = e.getChild();

	    if ( toolBarFocusListener != null )
	    {
	        c.removeFocusListener(
toolBarFocusListener );
	    }
	}

    } // end class ToolBarContListener


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

CUSTOMER WORKAROUND :
Save the border prior to adding the widget to the toolbar,
then restore the border after the add.
(Review ID: 137659)
======================================================================

                                    

Comments
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
mantis
mantis-b02

FIXED IN:
mantis
mantis-b02

INTEGRATED IN:
mantis
mantis-b02


                                     
2004-06-14
EVALUATION

This is still an issue and is very similar to the fixed bug 4510986. The issue is really in BasicToolBarUI.setBorderToRollover and setBorderToNormal in which the borders are swapped.

These methods should not clobber the user set Borders on the button - that was the motivation for looking at null borders as a special case.

The solution is to swap the borders only if the default borders for the buttons have been used. This can be simplified by only changing the border is it is an existing UIResource - a marker class that indicates that this is a default swing border. The following diffs would take care of the null case in 4510986 and this case.


------- BasicToolBarUI.java -------
679c679
< 	    if (b.getBorder() != null) {
---
> 	    if (b.getBorder() instanceof UIResource) {
705c705
< 	    if (b.getBorder() != null) {
---
> 	    if (b.getBorder() instanceof UIResource) {

Not a showstopper for hopper but will commit to mantis.

###@###.### 2002-05-06
                                     
2002-05-06



Hardware and Software, Engineered to Work Together