Rounded Border JPanel (JPanel graphics improvements) – CodeProject
Rounded Border JPanel (JPanel graphics improvements)
By b4rc0ll0 | 10 Oct 2010
JavaWindowsLinuxDesignIntermediateSwing
Reusable extension of JPanel with rounded borders, shadow and antialiasing
Sponsored Links
Introduction
Swing Framework extensibility allows us to create very advanced graphics component for a better view of our Jframes more than directly Look&Feel management, and more simply.
Basically a JComponent
is a void Bounded Box that can be added into swing containers.
It can be extended by a simple plain class, and overriding paintComponent
method, we can draw everything we need in a Bounded Box. In this way we can re-create all basic swing components like Buttons, Labels, Panels... with relative events.
Using the Code
In this case, we will review a JPanel
extension (instead of JComponent
extension) because we want to create a Container
component (like JPanel
!) but with some graphics improvements:
Collapse
public class RoundedPanel extends JPanel {
/** Stroke size. it is recommended to set it to 1 for better view */
protected int strokeSize = 1;
/** Color of shadow */
protected Color shadowColor = Color.black;
/** Sets if it drops shadow */
protected boolean shady = true;
/** Sets if it has an High Quality view */
protected boolean highQuality = true;
/** Double values for Horizontal and Vertical radius of corner arcs */
protected Dimension arcs = new Dimension(20, 20);
/** Distance between shadow border and opaque panel border */
protected int shadowGap = 5;
/** The offset of shadow. */
protected int shadowOffset = 4;
/** The transparency value of shadow. ( 0 - 255) */
protected int shadowAlpha = 150;
//FOLLOWING CODES GOES HERE
}
We have created a simple class extending JPanel. It has some properties for the improvements (see inline comments for properties descriptions).
Attention!! If you want to use this class directly in a visual GUI editor, like integrated Netbeans Editor, we must write a void
constructor, because Editor can't directly know constructor parameter of our components:
Collapse
public RoundedPanel() {
super();
setOpaque(false);
}
We call super()
father constructor and setOpaque(false)
to create a transparent void
bounded box, where we can freely draw custom component.
Now we can override the paintComponent
method:
Collapse
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
int shadowGap = this.shadowGap;
Color shadowColorA = new Color(shadowColor.getRed(),
shadowColor.getGreen(), shadowColor.getBlue(), shadowAlpha);
Graphics2D graphics = (Graphics2D) g;
//Sets antialiasing if HQ.
if (highQuality) {
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
}
//Draws shadow borders if any.
if (shady) {
graphics.setColor(shadowColorA);
graphics.fillRoundRect(
shadowOffset,// X position
shadowOffset,// Y position
width - strokeSize - shadowOffset, // width
height - strokeSize - shadowOffset, // height
arcs.width, arcs.height);// arc Dimension
} else {
shadowGap = 1;
}
//Draws the rounded opaque panel with borders.
graphics.setColor(getBackground());
graphics.fillRoundRect(0, 0, width - shadowGap,
height - shadowGap, arcs.width, arcs.height);
graphics.setColor(getForeground());
graphics.setStroke(new BasicStroke(strokeSize));
graphics.drawRoundRect(0, 0, width - shadowGap,
height - shadowGap, arcs.width, arcs.height);
//Sets strokes to default, is better.
graphics.setStroke(new BasicStroke());
}
The method has five macro sections. The header section calls super overridden method and declares main variables: (width
, height
) are the current size of our component; shadowGap
is an override of homonymous property, we will see later why; shadowColor
is the color property with transparency added; and graphics
is the Graphics
object passed by method parameters that represent the canvas where we can paint on (Graphics2D
cast is more powerful, see antialiasing).
The next section checks if highQuality
is true
, so enable antialiasing on canvas for all shapes drawn after.
Alike shady determinates if component draws shadow. Shadow is a simple roundRect
, usually black, with left-top and right-bottom corners parameterized by shadowOffset
value.
Above a possible shadow, the component draws the opaque panel with a thin edge. Here the right-top and right bottom positions are parameterized by shadowGap
.
Graphically the order 1) -> 2) -> 3) of layer must be this, due to overlap:
The footer section is used to reset parameters that we have distorted. In fact, if we will not reset strokes, the next component added to this panel will have a distorted border.
Conclusions
With these simple few lines, we have created a solid redestributable swing component that look like this:
We can see tree RoundedPanel
here: violet, green and blue one, each with a different arcs dimension that determinates the curvature of corners. The best size is [10,10] like blue panel, because an excessive curve (like violet) can cut out upper-inner components (try set [80,80] .. ).
License
This article, along with any associated source code and files, is licensed under The Apache License, Version 2.0
About the Author