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:
public class RoundedPanel extends JPanel {
protected int strokeSize = 1;
protected Color shadowColor = Color.black;
protected boolean shady = true;
protected boolean highQuality = true;
protected Dimension arcs = new Dimension(20, 20);
protected int shadowGap = 5;
protected int shadowOffset = 4;
protected int shadowAlpha = 150;
}
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:
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:
@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;
if (highQuality) {
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
}
if (shady) {
graphics.setColor(shadowColorA);
graphics.fillRoundRect(
shadowOffset,
shadowOffset,
width - strokeSize - shadowOffset,
height - strokeSize - shadowOffset,
arcs.width, arcs.height);
} else {
shadowGap = 1;
}
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);
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] .. ).