My child panels inherit their border width from their parent

Hi all,

I created a new Border (curved corners) using code that I found on these forums. Unfortunately, when I embed a child JPanel into a JPanel that is using this border, the child's border thickness becomes that of the parent's, even when the child's border thickness is explicitly set!

I don't have much experience creating my own borders, so it's possible that I've made a silly mistake.

Below is my source (self contained and excecutable). If you ran it you'd notice that the inner JPanel's border has a thickness of 10, even though it's been set to 1.

Any light you could shed on this problem would be great -- it's really screwing up my layout!

Thanks!

Sam

publicclass BorderTest{

public BorderTest(){

JPanel parent =new JPanel();

parent.setBorder(new EtchedRoundedBorder(EtchedRoundedBorder.RAISED, 50, 10));

JPanel child =new JPanel();

child.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));

parent.add(child);

JFrame frame =new JFrame();

frame.setContentPane(parent);

frame.pack();

frame.setVisible(true);

}

publicstaticvoid main(String[] args){

BorderTest b =new BorderTest();

}

privateclass EtchedRoundedBorderimplements Border{

protectedint etchType, radius;

protectedfloat width;

protected Color highlight, shadow;

publicstaticfinalint RAISED = 0, LOWERED = 1;

public EtchedRoundedBorder(){

this(LOWERED, 20, 1f);

}

public EtchedRoundedBorder(int etchType,int radius,float width){

this(etchType, radius, Color.WHITE, Color.BLACK, width);

}

public EtchedRoundedBorder(int etchType, Color highlight, Color shadow,

float width){

this(etchType, 20, highlight, shadow, width);

}

public EtchedRoundedBorder(int etchType,int radius, Color highlight,

Color shadow,float width){

this.etchType = etchType;

this.radius = radius;

this.highlight = highlight;

this.shadow = shadow;

this.width = width;

}

publicvoid paintBorder(Component c, Graphics g,int x,int y,

int width,int height){

int w = width;

int h = height;

int r = radius;

Graphics2D g2 = (Graphics2D) g;

final BasicStroke stroke =new BasicStroke(this.width,

BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f);

g2.setStroke(stroke);

g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,

RenderingHints.VALUE_ANTIALIAS_ON);

g.translate(x, y);

if (etchType == LOWERED){

g.setColor(getShadowColor(c));

g.drawRoundRect(0, 0, w - 2, h - 2, 2 * r, 2 * r);

}

g.setColor(etchType == LOWERED ? getHighlightColor(c)

: getShadowColor(c));

g.drawLine(1, h - r - 2, 1, r + 1);

g.drawLine(r + 1, 1, w - r - 2, 1);

g.drawLine(r, h - 1, w - r - 1, h - 1);

g.drawLine(w - 1, h - r - 1, w - 1, r);

int ax = 1;

int ay = 1;

int arcSide = 2 * r;

int startAngle = 90;

int arcAngle = 90;

g.drawArc(ax, ay, arcSide, arcSide, startAngle, arcAngle);// nw

ax = 1;

ay = h - 2 * r - 1;

startAngle = 180;

g.drawArc(ax, ay, arcSide, arcSide, startAngle, arcAngle);// sw

ax = w - 2 * r - 1;

ay = h - 2 * r - 1;

startAngle = -90;

g.drawArc(ax, ay, arcSide, arcSide, startAngle, arcAngle);// se

ax = w - 2 * r - 1;

ay = 1;

startAngle = 0;

g.drawArc(ax, ay, arcSide, arcSide, startAngle, arcAngle);// ne

if (etchType == RAISED){

g.setColor(getHighlightColor(c));

g.drawRoundRect(0, 0, w - 2, h - 2, 2 * r, 2 * r);

}

g.translate(-x, -y);

}

public Insets getBorderInsets(Component c){

int d = (int) (radius * Math.cos(Math.PI / 4) + 2);

returnnew Insets(d, d, d, d);

}

public Insets getBorderInsets(Component c, Insets insets){

int d = (int) (radius * Math.cos(Math.PI / 4) + 2);

insets.left = insets.top = insets.right = insets.bottom = d;

return insets;

}

publicboolean isBorderOpaque(){

returnfalse;

}

publicint getEtchType(){

return etchType;

}

public Color getHighlightColor(Component c){

return highlight !=null ? highlight : c.getBackground().brighter();

}

public Color getHighLightColor(){

return highlight;

}

public Color getShadowColor(Component c){

return shadow !=null ? shadow : c.getBackground().darker();

}

public Color getShadowColor(){

return shadow;

}

}

}

[8540 byte] By [Asbestosa] at [2007-11-27 10:33:18]
# 1

Ah, solved it myself.

I set the g2 stroke here

public void paintBorder(Component c, Graphics g, int x, int y,

int width, int height) {

...

Graphics2D g2 = (Graphics2D) g;

final BasicStroke stroke = new BasicStroke(this.width,

BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f);

g2.setStroke(stroke);

...

}

and then never un-set it. Adding this line to the bottom of the paint method

g2.setStroke(new BasicStroke());

solves the problem.

I would have thought that each component used it's own graphics2d, but I guess not?

Asbestosa at 2007-7-28 18:21:58 > top of Java-index,Desktop,Core GUI APIs...
# 2

Read the "The Graphics Object and Graphics2D" section from the painting tutorial for more background information on this topic.

http://java.sun.com/docs/books/tutorial/uiswing/painting/concepts2.html

It shows two approaches to solve the problem. You used the first approach, but I would suggest that you should not be creating a new BasicStroke object every time.

camickra at 2007-7-28 18:21:58 > top of Java-index,Desktop,Core GUI APIs...
# 3

Thanks for the link.

The article notes that the second method is to destroy the g2d object. This was actually the first thing I tried when I narrowed down the source of the project, but then the child panel did not get drawn at all.

This, in turn, was because I was not creating a new g2d object. But when I added the lineGraphics2D g2 = (Graphics2D) g.create();

the resulting border looked horrible -- no antialiasing or anything.

I'm not sure what I'm doing wrong, but it doesn't much matter because the first solution (and your tip) work fine for now.

Thanks!

Sam

Asbestosa at 2007-7-28 18:21:58 > top of Java-index,Desktop,Core GUI APIs...