Painting Borders Correctly

The golden rule of creating borders is: “Never paint in the component’s region.” Here’s a border that violates this rule:

public class WrongBorder extends AbstractBorder {
    public WrongBorder( ) {}
    public void paintBorder(Component c, Graphics g, int x, int y, 
                            int width, int height) {
        g.setColor(Color.black);
        g.fillRect(x, y, width, height);      // Bad
    }
    public boolean isBorderOpaque( ) { return true;}
    public Insets getBorderInsets(Component c) {
        return new Insets(20, 20, 20, 20);
    }
}

Look carefully at the paintBorder( ) method. The last four parameters passed in to the method can be used to calculate the total screen area of the component — including the border insets. We decided to paint our border by creating a single filled rectangle that fills the entire component space. While drawing the border, however, we painted over the underlying component and violated the golden rule.

The correct approach is to obtain the insets of the border region and draw rectangles only in that space, as shown:

public void paintBorder(Component c, Graphics g, int x, int y, 
                        int width, int height) {
    Insets insets = getBorderInsets(c);
    g.setColor(Color.black);

    //  Draw rectangles around the component, but do not draw
    //  in the component area itself.
    g.fillRect(x, y, width, insets.top); 
    g.fillRect(x, y, insets.left, height); 
    g.fillRect(x+width-insets.right, y, insets.right, height); 
    g.fillRect(x, y+height-insets.bottom, width, insets.bottom); 
}

The AbstractBorder Class

AbstractBorder

Get Java Swing, 2nd Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.