Graphics

The abstract class java.awt.Graphics provides a device independent interface for rendering graphics. When drawing on AWT components, you override the paint() method. When drawing on Swing components you override the paintComponent() method.
public class DrawingPanel extends JPanel {
  public void paintComponent (Graphics g) {
    g.setColor (Color.black);
    g.drawString ("Hello World!", 10, 50);
  }
  public static void main (String args[]) {
    JFrame frame = new JFrame ("Drawing Panel");
    DrawingPanel panel = new DrawingPanel();
    frame.getContentPane().add(panel);
    frame.setSize (200, 100);
    frame.setVisible (true);
    frame.addWindowListener (new WindowAdapter() {
	public void window Closing (WindowEvent evt) {
	  System.exit (0);
	}
    });
  }
}

Graphics Coordinate System

The graphics context uses a simple coordinate system in which each pixel is represented by its x and y coordinates. The origin of the coordinate system is located at the top left corner of the component. The x coordinate increases from left to right and the y coordinate increases from top to bottom.

Component Color and Graphics Color

Every component has two colors associated with it: a foreground and a background color. You set the colors by calling:
public void setBackground (Color c);
public void setForeground (Color c);

You can think of the graphics object as having a pen for drawing and a paintbrush for painting. When you use the g.setColor() method you set the color of both the pen and the paintbrush. Drawing refers to making a line drawing and is usually done by calling methods of the form drawX(). Painting refers to filling a bounded object with color. Methods of the form fillX() are for painting.

Color Class

Colors are created from an RGB value which is a collection of three numbers that specify the amount of red, green, and blue that are mixed together to form the color. The Color class has three constructors:
public Color (int r, int g, int b);       // range in values 0 to 255
public Color (int rgb);		          // rgb = 65536 * r + 256 * g + b
public Color (float r, float g, float b); // range in values 0.0 to 1.0

In theory it is possible to specify 256 x 256 x 256 = 16,777,216 different colors but in practice the actual colors that can be displayed depends on the quality of your system's monitor. There are 13 predefined colors - black, blue, cyan, darkGray, gray, gray, green, lightGray, magenta, orange, pink, red, white, and yellow.

The brighter() and darker() methods enable you to start with a standard color and lighten or darken it.

Color red = Color.red;	
Color brightRed = red.brighter();
Color darkRed = red.darker();

The RGB mixture (255, 255, 255) can be used to create pure white, while (0, 0, 0) is used to specify black. Shades of gray are colors whose RGB components have equal values. Thus (128, 128, 128) is the specification for Color.gray.

Rendering Text

Each graphics context has an associated Font and FontMetrics object and the Graphics class provides the following methods to access them:
Font getFont();		void setFont (Font f)
Font getFontMetrics();	

The Font class defines a constructor that can be used to obtain available fonts:

Font (String name, int style, int size)
Some common fonts are - Serif, SansSerif, Monospaced, Dialog, DialogInput, etc. To get all the fonts available on your system run the following piece of code:
GraphicsEnvironment ge = GrahpicsEnvironment.getLocalGraphicsEnvironment();
String[] fonts = ge.getAvailableFontFamilyNames();

Supported styles include PLAIN, BOLD, ITALIC, BOLD+ITALIC. The Font() constructor is designed to work with any set of arguments. If you input the name of a font that is not available the system will supply a default font.

The FontMetrics is an object that encapsulates important data about a font such as its height and width.

Text rendering in a component is done using the following methods. The string is drawn with the baseline of the first character at the specified coordinates, using the current font and color.

void drawString (String str, int x, int y)

Drawing Lines

The Graphics class provides the following method for drawing lines. The line is drawn from point (x1, y1) to point (x2, y2) using the current color.
void drawLine ( int x1, int y1, int x2, int y2)

Drawing Rectangles

The Graphics class provides methods for drawing the outlines of rectangles. Methods are also provided to fill the rectangles with the current color. The rectangle is specified by giving the coordinates of the top left corner, the width, and the height.
void drawRect (int x, int y, int width, int height)
void fillRect (int x, int y, int width, int height)
void drawRoundRect (int x, int y, int width, int height, int arcWidth, 
		    int arcHeight)
The parameters arcWidth and arcHeight specify the horizontal and vertical diameters of the arc at the four corners.
void draw3DRect (int x, int y, int width, int height,
			int arcWidth, int arcHeight, boolean raised)
The edges of the rectangle will be highlighted so that it appears as if the edges were beveled and lit from the upper left corner. The raised argument determines whether the rectangle appears to be raised above or sunk into the drawing surface.

Drawing Ovals

The Graphics class provides a method for drawing ovals (ellipses or circles). A method is provided to fill the oval with the current color. The oval is bounded by an invisible rectangle.
void drawOval (int x, int y,			// top left corner
		  int width, int height)
void fillOval (int x, int y, int width, int height)

Drawing Arcs

The Graphics class provides a method for drawing arcs. These arcs can be circular or elliptical. The starting point of the arc is given by a starting angle, and the ending point is given by the angle swept by the arc. Angles are measured in degrees. Positive angles are measured counter clockwise. The arc is bounded by a rectangle. The center of the arc coincides with the center of the bounding rectangle. A method is also provided to fill the area bounded by the arc and its two radii with the current color, resulting in a pie segment.
void drawArc (int x, int y,			// top left corner
		int width, int height,		// bounding rectangle
		int startAngle, int arcAngle)
void fillArc (int x, int y, int width, int height, 
	      int startAngle, int arcAngle)

Drawing Polygons

A polygon is a closed sequence of line segments. Given a sequence of points (called vertices), line segments connect one vertex to the next in the sequence, finishing with the last vertex being connected with the first one. The Polygon class has the following constructor
Polygon (int[] xpoints, int[] ypoints, int npoints)

The Graphics class provides the following methods for drawing polygons. The outline of the polygon is drawn or filled with the current color.

void drawPolygon (int[] xPoints, int[] yPoints, int nPoint)
void drawPolygon (Polygon p)
void fillPolygon (int[] xPoints, int[] yPoints, int nPoints)
void fillPolygon (Polygon p)

A polyline is an open figure, similar to a polygon, where the last vertex is not connected to the first one.

void drawPolyline (int[] xPoints, int[] yPoints, int nPoints)

Clipping

A Graphics object maintains a clip region. The clip region of a graphics context defines the area in which all drawing will be done. In other words, the clip region defines the actual drawing area used for rendering operations. The region can be all or part of the associated component. Rendering operations have no effect outside the clip region.
void setClip (int x, int y, int width, int height)

Sample Programs

The following program illustrates the drawing primitives.

import javax.swing.*;
import java.awt.*;

public class DrawingBoard extends JFrame
{
  public DrawingBoard ()
  {
    setTitle ( "Drawing Board" );
    getContentPane().add ( new DrawingPanel() );
  }

  public static void main ( String[] args )
  {
    DrawingBoard frame = new DrawingBoard ();

    frame.setSize ( 500, 600 );
    frame.setVisible ( true );
  }
}

class DrawingPanel extends JPanel
{
  public void paintComponent ( Graphics g )
  {
    super.paintComponent ( g );
	
    // Set the font
    g.setFont (new Font("Serif", Font.BOLD, 20));
    g.drawString ("Serif", 10, 30);
    g.setFont (new Font("SansSerif", Font.ITALIC, 20));
    g.drawString ("SansSerif", 150, 30);
    g.setFont (new Font ("Monospaced", Font.PLAIN, 20));
    g.drawString ("Monospaced", 300, 30);
	
    // Draw lines to form a T
    g.setColor (Color.red);
    g.drawLine (10, 50, 100, 50);
    g.setColor (Color.blue);
    g.drawLine (55, 50, 55, 150);

    // Draw rectangle and filled rounded square
    g.setColor (Color.orange);
    g.drawRect (150, 50, 50, 75);
    g.fillRoundRect (300, 50, 50, 75, 20, 20);	
		
    // 3D: Draw filled rectangle and square
    g.setColor (Color.green);
    g.fill3DRect (10, 200, 50, 75, true);
    g.draw3DRect (150, 200, 50, 50, true);

    // Draw an open and a filled ellipse
    g.setColor (Color.cyan);
    g.drawOval (250, 200, 50, 75);
    g.fillOval (350, 200, 50, 75);
		
    // Draw an open and a filled circle
    g.setColor (Color.magenta);
    g.drawOval (10, 300, 75, 75);
    g.fillOval (150, 300, 75, 75);

    // Draw arc to represent a Pac man
    g.setColor (Color.pink);
    g.drawArc (250, 300, 50, 50, 30, 300);
    g.fillArc (350, 300, 50, 50, 30, 300);		

    // Create a polygon
    int[] xPoints = {10, 30, 40, 50, 70, 50, 40, 30};
    int[] yPoints = {440, 430, 410, 430, 440, 450, 470, 450};
    int nPoints = xPoints.length;
    Polygon star = new Polygon (xPoints, yPoints, nPoints);
    g.setColor (Color.yellow);
    g.drawPolygon (star);
		
    // Put a box around the polygon
    g.setColor (Color.darkGray);
    Rectangle bounds = star.getBounds();
    g.drawRect (bounds.x, bounds.y, bounds.width, bounds.height);

    // Set the clipping region
    g.setClip (200, 400, 100, 100);
		
    // Draw Pac-man in a 500 x 600 area
    for (int i = 0; i < 500; i += 60)
      for (int j = 0; j < 600; j += 60)
        g.fillArc (i, j,		// top left hand corner
	           50, 50,		// width, height
	           30, 300);		// start angle, sweep angle	

  }
	
}

This program shows how you can use the primitives to draw graphs.


import javax.swing.*;
import java.awt.*;

public class DrawingGraph extends JFrame
{
  public DrawingGraph ()
  {
    setTitle ( "Drawing Graph" );
    getContentPane().add ( new DrawingPanel() );
  }

  public static void main ( String[] args )
  {
    DrawingGraph frame = new DrawingGraph ();

    frame.setSize ( 500, 500 );
    frame.setVisible ( true );
  }
}

class DrawingPanel extends JPanel
{
  public void paintComponent ( Graphics g )
  {
    super.paintComponent ( g );
	
    // Set up a Cartesian coordinate system

    // get the size of the drawing area		
    Dimension size = this.getSize();

    // place the origin at the middle
    g.translate (size.width / 2, size.height / 2);

    // draw the x and y axes
    drawXYAxes (g);
		
    graphLine (g, 0.5, 25.2);
    graphQuadratic (g, -0.125, 0, 0);

  }
	
  private void drawXYAxes (Graphics g) {
    Dimension size = this.getSize();
    int hBound = size.width / 2;
    int vBound = size.height / 2;
    int tic = size.width / 100;
			
    // draw the x-axis
    g.drawLine (-hBound, 0, hBound, 0);

    // draw the tic marks along the x axis
    for (int k = -hBound; k <= hBound; k += 10)
      g.drawLine (k, tic, k, -tic);
			
    // draw the y-axis
    g.drawLine (0, vBound, 0, -vBound);	

    // draw the tic marks along the y axis
    for (int k = -vBound; k <= vBound; k += 10)
      g.drawLine (-tic , k, +tic, k);					
  }
	
  private void graphLine (Graphics g, double a,  double b) {
    Dimension size = this.getSize();
    g.setColor (Color.red);
		
    int x1 = size.width / 2;
    int y1 = (int) ((a * x1) + b);
    y1 = - y1;
		
    int x2 = - x1;
    int y2 = (int)((a * x2) + b);
    y2 = - y2;
		
    g.drawLine (x1, y1, x2, y2);	
  }
	
  private void graphQuadratic (Graphics g, double a, double b, double c) {
    Dimension size = this.getSize();
    g.setColor (Color.blue);
	
    int hBound = size.width / 2;
    for (int i = -hBound; i <= hBound; i++) {
      int x1 = i;
      int y1 = (int) (a * x1 * x1 + b * x1 + c);
      y1 = - y1;
		
      int x2 = x1 + 1;
      int y2 = (int) (a * x2 * x2 + b * x2 + c);
      y2 = - y2;
					
      g.drawLine (x1, y1, x2, y2);
  }	
  
  }
}