Graphics and Java2D

Java has the capability to draw two-dimensional shapes, control colours and control fonts. Java2D offers more spohisticated drawing capabilities.

Below is a portion of the Java class hierarchy that includes several of the basic Graphic classes and Java2D API class.

Information on some of the classes above

Class Note
Color contains methods and contants for manipulating colours
Font contains methods and contants for manipulating fonts
FontMetrics contains methods for obtaining font information
Polygon contains methods for creating polygons, a polygon is a figure that is composed of a finite sequence of straight lines.
Graphics contains methods for drawing strings, lines, rectangles and other shapes
BasicStroke helps specify the drawing characteristics of lines
Gradient-Paint/ TexturePaint help specify the characteristics for filling shapes with colours and patterns.
GeneralPath represents a geometric path constructed from straight lines and quadratic and cubic curves.
Arc2D is the abstract superclass for all objects that store 2D arc defined by a bounding rectangle, start, angle, angular extent and closure type.
Ellipse2D describes an ellipse that is defined by a bounding rectangle
Line2D represents a line segment in (x,y) coordinate space
Rectangle2D describes a rectangle defined by a location(x,y) and dimension(w x h)
RoundRectangle2D describes a rectangle with rounded corners.

First we must understand Java's coordinate system, which is a scheme for identifying every possible point on the screen (monitor). By default the uuper left-hand corner has the coordinates (0,0). A coordinate pair consists of a x-coordinate (the horizontal coordinate) and the y-coordinate (the vertical coordinate). Coordinate units are measured in pixels. A pixel is a display monitor's smallest unit of resolution.

Graphics Contexts and Graphic Objects

A Java graphics context enables drawing on the screen. A Graphics object manages a graphics context by controlling how information is drawn, they contain methods for drawing, font manipulation, colour manipulation and the like. The Graphics class is a abstract class (cannot be instantiated) because each platform has a different way to implement drawing capabilities. Class Component is the superclass for many of the classes in the java.awt package.

Basic example import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

public class paintTest extends JFrame {
   public paintTest() {
      super( "paintTest Demo" );

      // Make the display size 400,130
      setSize( 400, 130 );

      // Now call the paint method
      show();
   }

   public void paint( Graphics g ) {
      // change the color and display some text
      g.setColor( new Color( 255, 0, 0 ) );
      g.drawString( "This should be at position 40,40" + g.getColor(), 40, 40 );
   }

   public static void main( String args[] ) {
      paintTest app = new paintTest();

      app.addWindowListener(
         new WindowAdapter() {
            public void windowClosing( WindowEvent e ) {
               System.exit( 0 );
            }
         }
      );
   }
}

Color Control

The Color class defines methods and contants for manipulating colours in a Java program. The predefined contants are as below

Colour Constant
Colour
RGB Value
public final static Color orange
orange
255, 200, 0
public final static Color pink
pink
255, 175, 175
public final static Color cyan
cyan
0, 255, 255
public final static Color magenta
magenta
255, 0, 255
public final static Color yellow
yellow
255, 255, 0
public final static Color black
black
0, 0, 0
public final static Color white
white
255, 255, 255
public final static Color gray
gray
128, 128, 128
public final static Color lightGray
light gray
192, 192, 192
public final static Color darkGray
dark gray
64, 64, 64
public final static Color red
red
255, 0, 0
public final static Color green
green
0, 255, 0
public final static Color blue
blue
0, 0, 255

The methods associated with Color manipulation

Color(int r, int g, int b) creates a color based on red, green, blue contents expressed as integers from 0 to 255
Color(float r, float g, float b) creates a color based on red, green, blue contents expressed as floats from 0.0 to 1.0
getRed() returns a value between 0 and 255 representing the red content
getGreen() returns a value between 0 and 255 representing the green content
getBlue() returns a value between 0 and 255 representing the blue content
getColor() Returns a Color object representing the current color for the graphics context
setColor() sets the current olor for drawing with the graphics context.

Here are a couple of examples

Color Example
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class ShowColors extends JFrame { public ShowColors() { super( "Using colors" ); setSize( 400, 130 ); show(); } public void paint( Graphics g ) { // set new drawing color using integers g.setColor( new Color( 255, 0, 0 ) ); g.fillRect( 25, 25, 100, 20 ); g.drawString( "Current RGB: " + g.getColor(), 130, 40 ); // set new drawing color using floats g.setColor( new Color( 0.0f, 1.0f, 0.0f ) ); g.fillRect( 25, 50, 100, 20 ); g.drawString( "Current RGB: " + g.getColor(), 130, 65 ); // set new drawing color using static Color objects g.setColor( Color.blue ); g.fillRect( 25, 75, 100, 20 ); g.drawString( "Current RGB: " + g.getColor(), 130, 90 ); // display individual RGB values Color c = Color.magenta; g.setColor( c ); g.fillRect( 25, 100, 100, 20 ); g.drawString( "RGB values: " + c.getRed() + ", " + c.getGreen() + ", " + c.getBlue(), 130, 115 ); } public static void main( String args[] ) { ShowColors app = new ShowColors(); app.addWindowListener( new WindowAdapter() { public void windowClosing( WindowEvent e ) { System.exit( 0 ); } } ); } }
Color Example
(using the JColorChooser)
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class ShowColors2 extends JFrame { private JButton changeColor; private Color color = Color.lightGray; private Container c; public ShowColors2() { super( "Using JColorChooser" ); c = getContentPane(); c.setLayout( new FlowLayout() ); changeColor = new JButton( "Change Color" ); changeColor.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent e ) { color = JColorChooser.showDialog( ShowColors2.this, "Choose a color", color ); if ( color == null ) color = Color.lightGray; c.setBackground( color ); c.repaint(); } } ); c.add( changeColor ); setSize( 400, 130 ); show(); } public static void main( String args[] ) { ShowColors2 app = new ShowColors2(); app.addWindowListener( new WindowAdapter() { public void windowClosing( WindowEvent e ) { System.exit( 0 ); } } ); } } Note: I will be talking about container, contentpane and layouts later

Font Control

The Font class defines methods and contants for manipulating fonts in a Java program. Some of the emtohds are from the Graphics class

Method or Constant
Class
Description
PLAIN
Font
A constant representing a plain font style
BOLD
Font
A constant representing a bold font style
ITALIC
Font
A constant representing a italic font style
Font(String name, int size)
Font
Creates a Font object with specified font, style and size
getStyle()
Font
Returns a integer indicating the current font style
getSize()
Font
Returns a integer indicating the current font size
getName()
Font
Returns the fonts name as a String
getFamily()
Font
Returns the fonts family as a String
isPlain()
Font
Returns true if font is a plain style
isBold()
Font
Returns true if font is a bold style
isItalic()
Font
Returns true if font is a italic style
getFont()
Graphics
Returns a font reference representing the current font
setFont(Font f)
Graphics
Sets the current font to the font, style and size specified by the font object reference
Font Metric Methods
getAscent()
FontMetrics
Returns a value representing the ascent of a font in points
getDescent()
FontMetrics
Returns a value representing the descent of a font in points
getLeading()
FontMetrics
Returns a value representing the leading of a font points
getHeight()
FontMetrics
Returns a value representing the height of a font in points
getFontMetrics()
FontMetrics
Returns FontMetrics object for the current drawing font.
getFontMetrics(Font f)
Graphics
Returns FontMetrics object for the specified font argument

Here are some examples

Font example One
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Fonts extends JFrame { public Fonts() { super( "Using fonts" ); setSize( 420, 125 ); show(); } public void paint( Graphics g ) { // set current font to Serif (Times), bold, 12pt // and draw a string g.setFont( new Font( "Serif", Font.BOLD, 12 ) ); g.drawString( "Serif 12 point bold.", 20, 50 ); // set current font to Monospaced (Courier), // italic, 24pt and draw a string g.setFont( new Font( "Monospaced", Font.ITALIC, 24 ) ); g.drawString( "Monospaced 24 point italic.", 20, 70 ); // set current font to SansSerif (Helvetica), // plain, 14pt and draw a string g.setFont( new Font( "SansSerif", Font.PLAIN, 14 ) ); g.drawString( "SansSerif 14 point plain.", 20, 90 ); // set current font to Serif (times), bold/italic, // 18pt and draw a string g.setColor( Color.red ); g.setFont( new Font( "Serif", Font.BOLD + Font.ITALIC, 18 ) ); g.drawString( g.getFont().getName() + " " + g.getFont().getSize() + " point bold italic.", 20, 110 ); } public static void main( String args[] ) { Fonts app = new Fonts(); app.addWindowListener( new WindowAdapter() { public void windowClosing( WindowEvent e ) { System.exit( 0 ); } } ); } }
Font example Two
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;


public class Metrics extends JFrame {
   public Metrics()
   {
      super( "Demonstrating FontMetrics" );
      
      setSize( 510, 210 );
      show();
   }

   public void paint( Graphics g )             
   {
      g.setFont( new Font( "SansSerif", Font.BOLD, 12 ) );
      FontMetrics fm = g.getFontMetrics();
      g.drawString( "Current font: " + g.getFont(), 10, 40 );
      g.drawString( "Ascent: " + fm.getAscent(), 10, 55 );
      g.drawString( "Descent: " + fm.getDescent(), 10, 70 );
      g.drawString( "Height: " + fm.getHeight(), 10, 85 );
      g.drawString( "Leading: " + fm.getLeading(), 10, 100 );

      Font font = new Font( "Serif", Font.ITALIC, 14 );
      fm = g.getFontMetrics( font );
      g.setFont( font );
      g.drawString( "Current font: " + font, 10, 130 );
      g.drawString( "Ascent: " + fm.getAscent(), 10, 145 );
      g.drawString( "Descent: " + fm.getDescent(), 10, 160 );
      g.drawString( "Height: " + fm.getHeight(), 10, 175 );
      g.drawString( "Leading: " + fm.getLeading(), 10, 190 );
   }

   public static void main( String args[] )
   {
      Metrics app = new Metrics();

      app.addWindowListener(
         new WindowAdapter() {
            public void windowClosing( WindowEvent e )
            {
               System.exit( 0 );
            }
         }
      );
   }
}

Drawing Lines, Rectangles, Ovals and Arcs

There are a variety of Graphics methods for drawing lines, rectangles and ovals, you must supply a width and height parameter (must be positive values) otherwise the drawing will not appear.

drawLine(int x1, int y1, int x2, int x2) Draws a line between point (x1, y1) and (x2, y2)
drawRect(int x, int y, int width, int height) Draws a rectangle of specified width/height, located at (x,y)
fillRect(int x, int y, int width, int height) Draws a solid rectangle of specified width/height, located at (x,y)
clearRect(int x, int y, int width, int height) Draws a solid rectangle of specified width/height, located at (x,y) as the same color as the background
drawRoundRect( int x, int y, int width, int height,
                        int arcWidth, int arcHeight)
Draws a rectangle with rounded corners of specified width/height, located at (x,y), the arcWidth and arcHeight determine the rounding of the corners
fillRoundRect( int x, int y, int width,
                    int height, int arcWidth, int arcHeight)
Draws a solid rectangle with rounded corners of specified width/height, located at (x,y), the arcWidth and arcHeight determine the rounding of the corners
draw3DRect(in x, int y, int width, int height, boolean b) Draws a three-dimensional rectangle of specified width/height, located at (x,y), The rectangle will appear raised when b is trueand lowered when b is false
fill3DRect(in x, int y, int width, int height, boolean b) Draws a filled three-dimensional rectangle of specified width/height, located at (x,y), The rectangle will appear raised when b is trueand lowered when b is false
drawOval(int x, int y, int width, int height) Draws a oval of specified width/height, located at (x,y), the oval touches all four sides of the bounding rectangle at the center of each side
fillOval(int x, int y, int width, int height) Draws a filled oval of specified width/height, located at (x,y), the oval touches all four sides of the bounding rectangle at the center of each side

Here are some examples

Example One
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;


public class LinesRectsOvals extends JFrame {
   private String s = "Using drawString!";

   public LinesRectsOvals()
   {
      super( "Drawing lines, rectangles and ovals" );

      setSize( 400, 165 );
      show();
   }

   public void paint( Graphics g )
   {
      g.setColor( Color.red );
      g.drawLine( 5, 30, 350, 30 );

      g.setColor( Color.blue );
      g.drawRect( 5, 40, 90, 55 );
      g.fillRect( 100, 40, 90, 55 );

      g.setColor( Color.cyan );
      g.fillRoundRect( 195, 40, 90, 55, 50, 50 );
      g.drawRoundRect( 290, 40, 90, 55, 20, 20 );

      g.setColor( Color.yellow );   
      g.draw3DRect( 5, 100, 90, 55, true );
      g.fill3DRect( 100, 100, 90, 55, false );

      g.setColor( Color.magenta );
      g.drawOval( 195, 100, 90, 55 );
      g.fillOval( 290, 100, 90, 55 );
   }

   public static void main( String args[] )
   {
      LinesRectsOvals app = new LinesRectsOvals();

      app.addWindowListener(
         new WindowAdapter() {
            public void windowClosing( WindowEvent e )
            {
               System.exit( 0 );
            }
         }
      );
   }
}
Example Two
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;


public class DrawArcs extends JFrame {
   public DrawArcs()
   {
      super( "Drawing Arcs" );

      setSize( 300, 170 );
      show();
   }

   public void paint( Graphics g )
   {
      // start at 0 and sweep 360 degrees
      g.setColor( Color.yellow );
      g.drawRect( 15, 35, 80, 80 );
      g.setColor( Color.black );
      g.drawArc( 15, 35, 80, 80, 0, 360 );

      // start at 0 and sweep 110 degrees
      g.setColor( Color.yellow );
      g.drawRect( 100, 35, 80, 80 );
      g.setColor( Color.black );
      g.drawArc( 100, 35, 80, 80, 0, 110 );

      // start at 0 and sweep -270 degrees
      g.setColor( Color.yellow );
      g.drawRect( 185, 35, 80, 80 );
      g.setColor( Color.black );
      g.drawArc( 185, 35, 80, 80, 0, -270 );

      // start at 0 and sweep 360 degrees
      g.fillArc( 15, 120, 80, 40, 0, 360 );

      // start at 270 and sweep -90 degrees
      g.fillArc( 100, 120, 80, 40, 270, -90 );
                 
      // start at 0 and sweep -270 degrees
      g.fillArc( 185, 120, 80, 40, 0, -270 );
   }

   public static void main( String args[] )
   {
      DrawArcs app = new DrawArcs();

      app.addWindowListener(
         new WindowAdapter() {
            public void windowClosing( WindowEvent e )
            {
               System.exit( 0 );
            }
         }
      );
   }
}

Drawing Polygons and Polylines

Polygons are multisided shapes, Polylines are a series of connected points.

drawPolygon( int xPoints[ ], int yPoints[ ], int points) Draws a polygon, this methods draws a closed polygon - even if the last point is different that the first point
drawPolyline( int xPoints[ ], int yPoints[ ], int points) Draws a series of connected lines, if the last point does not match the first point the polyline is not closed
drawPolygon( Polygon p) Draws the specified closed polygon
fillPolygon(int xPoints[ ], int yPoints[ ], int points) Draws a solid polygon, this methods draws a closed polygon - even if the last point is different that the first point
fillPolygon( Polygon p) Draws the specified closed solid polygon.
Polygon Constructs a new polygon object, the poly does not contain any points
Polygon(int xValues[ ], int yValues[ ], int numberOfPoints) Constructs a new polygon object, using the specified values

Here is an example

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


public class DrawPolygons extends JFrame {
   public DrawPolygons()
   {
      super( "Drawing Polygons" );

      setSize( 275, 230 );
      show();
   }

   public void paint( Graphics g )
   {
      int xValues[] = { 20, 40, 50, 30, 20, 15 };
      int yValues[] = { 50, 50, 60, 80, 80, 60 };
      Polygon poly1 = new Polygon( xValues, yValues, 6 );

      g.drawPolygon( poly1 );

      int xValues2[] = { 70, 90, 100, 80, 70, 65, 60 };
      int yValues2[] = { 100, 100, 110, 110, 130, 110, 90 };

      g.drawPolyline( xValues2, yValues2, 7 );

      int xValues3[] = { 120, 140, 150, 190 };
      int yValues3[] = { 40, 70, 80, 60 };

      g.fillPolygon( xValues3, yValues3, 4 );

      Polygon poly2 = new Polygon();
      poly2.addPoint( 165, 135 );
      poly2.addPoint( 175, 150 );
      poly2.addPoint( 270, 200 );
      poly2.addPoint( 200, 220 );
      poly2.addPoint( 130, 180 );

      g.fillPolygon( poly2 );
   }

   public static void main( String args[] )
   {
      DrawPolygons app = new DrawPolygons();

      app.addWindowListener(
         new WindowAdapter() {
            public void windowClosing( WindowEvent e )
            {
               System.exit( 0 );
            }
         }
      );
   }
}

Java2D API

The Java2D API provides advanced two-dimensional graphic capabilities for programmers who require detailed and complex graphical manipulations, the API includes features for processing line art, text and images. I will only touch a small sample of what the Java2D API is capable of for further information see Sun's Java2d website.

Drawing with the Java2D API is accomplished with an instance of class Graphics2D, which is a subclass of class Graphics.

Here are a couple of examples to get you going

Example One
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;


public class Shapes extends JFrame {
   public Shapes() 
   {
      super( "Drawing 2D shapes" );

      setSize( 425, 160 );
      show();
   }

   public void paint( Graphics g )
   {
      // create 2D by casting g to Graphics2D
      Graphics2D g2d = ( Graphics2D ) g;

      // draw 2D ellipse filled with a blue-yellow gradient
      g2d.setPaint(
         new GradientPaint( 5, 30,         // x1, y1
                            Color.blue,    // initial Color
                            35, 100,       // x2, y2
                            Color.yellow,  // end Color
                            true ) );      // cyclic
      g2d.fill( new Ellipse2D.Double( 5, 30, 65, 100 ) );

      // draw 2D rectangle in red
      g2d.setPaint( Color.red );                  
      g2d.setStroke( new BasicStroke( 10.0f ) ); 
      g2d.draw(
         new Rectangle2D.Double( 80, 30, 65, 100 ) );

      // draw 2D rounded rectangle with a buffered background
      BufferedImage buffImage =
         new BufferedImage(
            10, 10, BufferedImage.TYPE_INT_RGB );

      Graphics2D gg = buffImage.createGraphics();   
      gg.setColor( Color.yellow ); // draw in yellow
      gg.fillRect( 0, 0, 10, 10 ); // draw a filled rectangle
      gg.setColor( Color.black );  // draw in black
      gg.drawRect( 1, 1, 6, 6 );   // draw a rectangle
      gg.setColor( Color.blue );   // draw in blue
      gg.fillRect( 1, 1, 3, 3 );   // draw a filled rectangle
      gg.setColor( Color.red );    // draw in red
      gg.fillRect( 4, 4, 3, 3 );   // draw a filled rectangle

      // paint buffImage onto the JFrame
      g2d.setPaint(
         new TexturePaint(
            buffImage, new Rectangle( 10, 10 ) ) );
      g2d.fill(
         new RoundRectangle2D.Double(
            155, 30, 75, 100, 50, 50 ) );

      // draw 2D pie-shaped arc in white
      g2d.setPaint( Color.white );
      g2d.setStroke( new BasicStroke( 6.0f ) ); 
      g2d.draw(
         new Arc2D.Double(
            240, 30, 75, 100, 0, 270, Arc2D.PIE ) );

      // draw 2D lines in green and yellow
      g2d.setPaint( Color.green );
      g2d.draw( new Line2D.Double( 395, 30, 320, 150 ) );

      float dashes[] = { 10 };

      g2d.setPaint( Color.yellow );    
      g2d.setStroke(
         new BasicStroke( 4,                      
                          BasicStroke.CAP_ROUND,  
                          BasicStroke.JOIN_ROUND, 
                          10, dashes, 0 ) );      
      g2d.draw( new Line2D.Double( 320, 30, 395, 150 ) );
   }

   public static void main( String args[] )
   {
      Shapes app = new Shapes();

      app.addWindowListener(
         new WindowAdapter() {
            public void windowClosing( WindowEvent e )
            {
               System.exit( 0 );
            }
         }
      );
   }
}
Example Two
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.awt.geom.*;


public class Shapes2 extends JFrame {
   public Shapes2()
   {
      super( "Drawing 2D Shapes" );

      setBackground( Color.yellow );
      setSize( 400, 400 );
      show();
   }

   public void paint( Graphics g )
   {
      int xPoints[] = 
         { 55, 67, 109, 73, 83, 55, 27, 37, 1, 43 };
      int yPoints[] = 
         { 0, 36, 36, 54, 96, 72, 96, 54, 36, 36 };

      Graphics2D g2d = ( Graphics2D ) g;

      // create a star from a series of points
      GeneralPath star = new GeneralPath();

      // set the initial coordinate of the General Path
      star.moveTo( xPoints[ 0 ], yPoints[ 0 ] );

      // create the star--this does not draw the star
      for ( int k = 1; k < xPoints.length; k++ )
         star.lineTo( xPoints[ k ], yPoints[ k ] );

      // close the shape
      star.closePath();

      // translate the origin to (200, 200)
      g2d.translate( 200, 200 );

      // rotate around origin and draw stars in random colors
      for ( int j = 1; j <= 20; j++ ) {
         g2d.rotate( Math.PI / 10.0 );
         g2d.setColor(
            new Color( ( int ) ( Math.random() * 256 ),
                       ( int ) ( Math.random() * 256 ),              
                       ( int ) ( Math.random() * 256 ) ) );
         g2d.fill( star );   // draw a filled star
      }
   }

   public static void main( String args[] )
   {
      Shapes2 app = new Shapes2();

      app.addWindowListener(
         new WindowAdapter() {
            public void windowClosing( WindowEvent e )
            {
               System.exit( 0 );
            }
         }
      );
   }
}