Java Graphics  «Prev  Next»

Lesson 2AWT / Java 2D Painting
ObjectiveDraw text and shapes with Graphics/Graphics2D, using modern Swing painting on the EDT.

Graphics in AWT and Java 2D (Modern Usage)

Why this page was updated: The original text focused on applets and paint() on AWT components. Applets are removed from modern Java, and desktop painting should use Swing’s JComponent#paintComponent with Graphics2D. This revision updates the concepts, code, and terminology.

Graphics vs Graphics2D

AWT exposes an abstract drawing surface via java.awt.Graphics. In practice you’ll usually receive a Graphics2D instance (a subclass) that enables Java 2D features: antialiasing, strokes, transforms, composites, and advanced paints.

Where painting happens today

In Swing, custom painting belongs in paintComponent(Graphics g) of a JComponent (e.g., JPanel). Always call super.paintComponent(g) first and perform drawing afterward. Swing handles double buffering.



// A minimal, modern painting example (runs on Java SE 8+)
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;

public class PaintingDemo {
  public static void main(String[] args) {
    SwingUtilities.invokeLater(() -> {
      JFrame f = new JFrame("AWT / Java 2D Painting");
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.setContentPane(new CanvasPanel());
      f.pack();
      f.setLocationByPlatform(true);
      f.setVisible(true);
    });
  }

  static final class CanvasPanel extends JPanel {
    CanvasPanel() {
      setBackground(new Color(0xF7F7FA));
      setPreferredSize(new Dimension(520, 320));
    }
    @Override protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g.create();
      try {
        // 1) Rendering hints (antialias)
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);

        // 2) Paint (color/gradient) and Stroke (line style)
        g2.setPaint(new GradientPaint(20, 20, new Color(0x3B82F6),
                                      200, 120, new Color(0x06B6D4)));
        g2.fill(new RoundRectangle2D.Double(20, 20, 200, 120, 18, 18));

        g2.setStroke(new BasicStroke(3f));
        g2.setPaint(new Color(0x111827));
        g2.draw(new Ellipse2D.Double(260, 30, 120, 120));

        // 3) Font and text
        g2.setFont(new Font("SansSerif", Font.BOLD, 16));
        g2.drawString("Hello, Java 2D!", 20, 180);

        // 4) Transform (rotate and draw again)
        AffineTransform old = g2.getTransform();
        g2.rotate(Math.toRadians(-12), 340, 210);
        g2.setPaint(new Color(0xEF4444));
        g2.fill(new Rectangle2D.Double(300, 180, 160, 60));
        g2.setPaint(Color.WHITE);
        g2.drawString("Transformed", 315, 215);
        g2.setTransform(old);

      } finally {
        g2.dispose(); // release the Graphics context copy
      }
    }
  }
}
  


Core drawing attributes (Java 2D)

Java 2D text metrics: baseline, ascent, descent, leading, and bounds Diagram showing the text baseline with ascent, x-height hint, descent, leading, and the string bounds box for the word Java2D; guides include labels and arrows. y x ascent baseline descent leading Java2D
ascent descent leading Baseline: text sits on this line. Ascent rises above, descent drops below. Bounds: shown as a rounded rectangle; actual glyph outlines may extend slightly beyond.
Figure: Java 2D text baseline and FontMetrics
  • Baseline: Characters are positioned so their glyphs sit on this line.
  • Ascent / Descent: Distances above/below baseline that accommodate tallest ascenders and lowest descenders.
  • Leading: Extra recommended space following descent to the next baseline.
  • Bounds: Approximate string rectangle; useful for layout/centering with FontMetrics.

Coordinate system

The origin (0,0) is the top‑left of the component; +x grows rightward, +y downward. Units are device pixels unless a transform is applied. Java 2D uses a double‑precision user space that’s mapped to device space, enabling crisp vector graphics and resolution independence.

Working with colors, background, and fonts

Text Rendering and FontMetrics

Java 2D coordinate system with sample shapes Diagram showing origin at top-left with x axis to the right and y axis downward, plus a rounded rectangle with gradient fill, a dashed ellipse outline, and a rotated rectangle.
x → y ↓ origin (0,0) RoundRectangle2D + GradientPaint Ellipse2D + dashed Stroke Transformed AffineTransform (rotate)
Figure: Java 2D coordinate system and basic shapes
  • Axes: Origin at the top‑left; x increases to the right, y increases downward.
  • Paint & Stroke: Rounded rectangle uses a blue→cyan gradient; ellipse demonstrates a dashed stroke.
  • Transforms: The red label block is rotated via an AffineTransform.
  • Text: Vector text is positioned in user space and renders crisply at any scale.

Best practices

When to use AWT/Swing vs JavaFX

Quick reference: common operations


// Lines and shapes
g2.setPaint(Color.BLACK);
g2.draw(new Line2D.Double(10, 10, 120, 10));
g2.fill(new Rectangle2D.Double(10, 20, 80, 40));

// Stroke styles
g2.setStroke(new BasicStroke(5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER, 10f, new float[]{10f, 6f}, 0f));
g2.draw(new Ellipse2D.Double(120, 20, 80, 40));

// Text
g2.setFont(new Font("SansSerif", Font.PLAIN, 14));
g2.drawString("Sample", 12, 90);

// Images
// BufferedImage img = ImageIO.read(path);
// g2.drawImage(img, 200, 30, this);
  

SEMrush Software