Skip to main content

On This Page

Drawing Crisp Circles in Java with Graphics2D and BufferedImage

2 min read
Share

These articles are AI-generated summaries. Please check the original sources for full details.

Draw a Decent Looking Circle in Java | Baeldung

Daniel Fintinariu demonstrates how to render high-quality circles in Java Swing. The article highlights that Java2D’s Ellipse2D.Double API with rendering hints produces smoother results than drawOval() for scalable UI components.

Why This Matters

Ideal geometric shapes require perfect antialiasing and stroke control, but raster displays introduce pixelation. At 12–24px sizes, even antialiased circles show uneven stroke widths due to subpixel rounding errors. The cost of ignoring this is inconsistent UI elements across platforms, impacting user experience in dashboards and icons.

Key Insights

  • “Antialiasing + stroke control improves small-circle rendering, 2025”
  • “Ellipse2D.Double over drawOval() for composable shapes”
  • “BufferedImage used by Stripe for icon consistency in UI components”

Working Example

public final class CirclePanel extends JPanel {
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g.create();
        try {
            double diameter = Math.min(getWidth(), getHeight()) - 12 - 2;
            double cx = getWidth() / 2.0;
            double cy = getHeight() / 2.0;
            double x = cx - diameter / 2.0;
            double y = cy - diameter / 2.0;
            Shape circle = new Ellipse2D.Double(x, y, diameter, diameter);
            
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
            
            g2.setPaint(new Color(0xBBDEFB));
            g2.fill(circle);
            g2.setPaint(new Color(0x0D47A1));
            g2.setStroke(new BasicStroke(2f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
            g2.draw(circle);
        } finally {
            g2.dispose();
        }
    }
}
BufferedImage makeSupersampledCircle(int finalSize, int scale, float stroke) {
    int hi = finalSize * scale;
    BufferedImage img = new BufferedImage(hi, hi, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2 = img.createGraphics();
    try {
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
        double d = hi - stroke;
        Shape circle = new Ellipse2D.Double(stroke / 2.0, stroke / 2.0, d, d);
        g2.setPaint(new Color(0xBBDEFB));
        g2.fill(circle);
        g2.setPaint(new Color(0x0D47A1));
        g2.setStroke(new BasicStroke(stroke, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
        g2.draw(circle);
    } finally {
        g2.dispose();
    }
    return img;
}

Practical Applications

  • Use Case: Badge icons in dashboards with transparent backgrounds
  • Pitfall: Skipping RenderingHints.VALUE_STROKE_PURE causes inconsistent stroke widths on small circles

References:


Continue reading

Next article

Drawing a Quality Circle in Java Swing

Related Content