JDK-4189266 : component should not paint under its border
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.2.0
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: generic
  • CPU: generic
  • Submitted: 1998-11-11
  • Updated: 1998-11-16
  • Resolved: 1998-11-16
Description

Name: rk38400			Date: 11/11/98


import com.sun.java.swing.border.*;
import com.sun.java.swing.*;
import java.awt.event.*;
import java.awt.*;

/**
Demonstrate paint under border behavior.
I assert that it should be possible to have an opaque component with
a transparent border.
This is true if the border should show some portion
of the underlying components.

The upper right button demonstrates the desired behavior.
To get it, I overrode the paint method and set a clip rect.
That work-around broke the empty border, as evidenced by the
upper left button.

The two "default paint" buttons in the third row show the
undesirable paint under border behavior that occurs without the
clipping work-around.
*/
public class BorderPaint
extends AbstractBorder
  {
  private Insets borderInsets;
  private Dimension drop;

  public BorderPaint()
    {
    borderInsets = new Insets(0,0,10,10);
    drop = new Dimension(7,7);
    }

  /**
  Paint a lovely shadow.
  */
  public void paintBorder(Component c, Graphics g,
                          int x, int y,
                          int width, int height)
    {
    // color of the component
    Color cColor = c.getBackground();

    // color of the parent, if any.
    Component parent = c.getParent();
    Color pColor;
    if (parent != null)
      {
      pColor = parent.getBackground();
      }
    else
      {
      pColor = cColor;
      }

    // draw the shadow
    Color sColor = pColor.darker().darker();
    g.setColor(sColor);

    // Bottom
    g.fillRect(x + borderInsets.left + drop.width,
               y+height-borderInsets.bottom,
               width-borderInsets.left-drop.width,
               borderInsets.bottom);
    // Right
    g.fillRect(x + width-borderInsets.right,
               y + borderInsets.top + drop.height,
               borderInsets.right,
               height-borderInsets.bottom-drop.height);
    }

  /**
  Return the lovely size of the border.
  */
  public Insets getBorderInsets(Component c)
    {
    return (Insets)borderInsets.clone();
    }

  private static void addButton(Container c, Object constraint,
                                boolean opaque, boolean clip, boolean eborder)
    {
    JButton button;
    String name = opaque ? "opaque:" : "transparent:";
    name += eborder ? "empty:" : "custom:";

    if (clip)
      {
      button = new JButton(name+"clipped paint")
        {
        public void paint(Graphics g)
          {
          super.paintBorder(g);
          Rectangle r = getBounds();
          Insets ins = getInsets();
          g.clipRect(ins.left,ins.top,r.width-ins.left-ins.right,
                     r.height-ins.top-ins.bottom);
          super.paint(g);
          }
        };
      }
    else
      {
      button = new JButton(name+"default paint");
      }

    if (opaque)
      {
      button.setBackground(Color.blue);
      button.setForeground(Color.white);
      }

    if (eborder)
      {
      button.setBorder(new EmptyBorder(0,0,10,10));
      }
    else
      {
      button.setBorder(new BorderPaint());
      }

    c.add(button, constraint);
    }

  public static void main (String[] args)
    {
    JFrame f = new JFrame();
    Container c = f.getContentPane();
    c.setLayout(new GridBagLayout());
    f.setTitle("BorderPaint Test");

    GridBagConstraints cons = new GridBagConstraints();
    cons.insets = new Insets(10,10,10,10);
    cons.fill = cons.NONE;
    cons.ipady = 20;
    cons.ipadx = 10;
    for (int i = 0; i < 8; ++i)
      {
      cons.gridx = i/4;
      cons.gridy = i%4;
      addButton(c,cons,i%2==0,i%4<2,i<4);
      }

    f.addWindowListener(new WindowAdapter()
      {
      public void windowClosing(WindowEvent e) { System.exit(0); }
      });
    f.pack();
    f.show();
    }
  }
(Review ID: 41559)
======================================================================

Comments
EVALUATION The border is considered part of the component. If you would like the border to be transparent, the component must be transparent as well (setOpaque(false)). In this case the component will not draw its background and the parent will show through. scott.violet 1998-11-16
11-06-2004

WORK AROUND Name: rk38400 Date: 11/11/98 see number 5. ======================================================================
11-06-2004

PUBLIC COMMENTS The border is considered part of the component. If you would like the border to be transparent, the component must be transparent as well (setOpaque(false)). In this case the component will not draw its background and the parent will show through. scott.violet 1998-11-16
10-06-2004