thinkapjava 5.1.2 documentation

Graphics

«  GridWorld: Part 3   ::   Contents   ::   Input and Output in Java  »

Graphics

Java 2D Graphics

This appendix provides examples and exercises that demonstrate Java graphics. There are several ways to create graphics in Java; the simplest is to use java.awt.Graphics. Here is a complete example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.awt.Canvas;
import java.awt.Graphics;
import javax.swing.JFrame;

public class MyCanvas extends Canvas {

    public static void main(String[] args) {
        // make the frame
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // add the canvas
        Canvas canvas = new MyCanvas();
        canvas.setSize(400, 400);
        frame.getContentPane().add(canvas);

        // show the frame
        frame.pack();
        frame.setVisible(true);
    }

    public void paint(Graphics g) {
        // draw a circle
        g.fillOval(100, 100, 200, 200);
    }
}

You can download MyCanvas.java.

The first lines import the classes we need from java.awt and javax.swing.

MyCanvas extends Canvas, which means that a MyCanvas object is a kind of Canvas that provides methods for drawing graphical objects.

In main we

  1. Create a JFrame, which is a window that can contain the canvas, buttons, menus, and other window components;
  2. Create MyCanvas, set its width and height, and add it to the frame; and
  3. Display the frame on the screen.

paint is a special method that gets invoked when MyCanvas needs to be drawn. If you run this code, you should see a black circle on a gray background.

Graphics methods

To draw on the Canvas, you invoke methods on the Graphics object. The previous example uses fillOval. Other methods include drawLine, drawRect and more. You can read the documentation of these methods here.

Here is the prototype for fillOval:

public void fillOval(int x, int y, int width, int height)

The parameters specify a bounding box, which is the rectangle in which the oval is drawn (as shown in the figure). The bounding box itself is not drawn.

image

x and y specify the the location of the upper-left corner of the bounding box in the Graphics coordinate system.

Coordinates

You are probably familiar with Cartesian coordinates in two dimensions, where each location is identified by an x-coordinate (distance along the x-axis) and a y-coordinate. By convention, Cartesian coordinates increase to the right and up, as shown in the figure.

image

By convention, computer graphics systems to use a coordinate system where the origin is in the upper-left corner, and the direction of the positive y-axis is down. Java follows this convention.

Coordinates are measured in pixels; each pixel corresponds to a dot on the screen. A typical screen is about 1000 pixels wide. Coordinates are always integers. If you want to use a floating-point value as a coordinate, you have to round it off (see Section Converting from double to int).

Color

To choose the color of a shape, invoke setColor on the Graphics object:

g.setColor(Color.red);

setColor changes the current color; everything that gets drawn is the current color.

Color.red is a value provided by the Color class; to use it you have to import java.awt.Color. Other colors include:

black     blue    cyan   darkGray   gray   lightGray
magenta   orange  pink   red        white  yellow

You can create other colors by specifying red, green and blue (RGB) components. See here.

You can control the background color of the Canvas by invoking Canvas.setBackground.

Mickey Mouse

Let’s say we want to draw a picture of Mickey Mouse. We can use the oval we just drew as the face, and then add ears. To make the code more readable, let’s use Rectangles to represent bounding boxes.

Here’s a method that takes a Rectangle and invokes fillOval.

public void boxOval(Graphics g, Rectangle bb) {
    g.fillOval(bb.x, bb.y, bb.width, bb.height);
}

And here’s a method that draws Mickey:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public void mickey(Graphics g, Rectangle bb) {
    boxOval(g, bb);

    int dx = bb.width/2;
    int dy = bb.height/2;
    Rectangle half = new Rectangle(bb.x, bb.y, dx, dy);

    half.translate(-dx/2, -dy/2);
    boxOval(g, half);

    half.translate(dx*2, 0);
    boxOval(g, half);
}

The first line draws the face. The next three lines create a smaller rectangle for the ears. We translate the rectangle up and left for the first ear, then right for the second ear.

The result looks like this:

image

You can download Mickey.java.

Glossary

coordinate:
A variable or value that specifies a location in a two-dimensional graphical window.
pixel:
The unit in which coordinates are measured.
bounding box:
A common way to specify the coordinates of a rectangular area.

Exercises

Exercise

Draw the flag of Japan, a red circle on white background that is wider than it is tall.

Exercise

Modify Mickey.java to draw ears on the ears, and ears on those ears, and more ears all the way down until the smallest ears are only 3 pixels wide.

The result should look like Mickey Moose:

image

Hint: you should only have to add or modify a few lines of code.

You can download a solution.

Exercise

  1. Download Moire.java and import it into your development environment.

  2. Read the paint method and draw a sketch of what you expect it to do. Now run it. Did you get what you expected? For an explanation of what is going on, see Wikipedia.

  3. Modify the program so that the space between the circles is larger or smaller. See what happens to the image.

  4. Modify the program so that the circles are drawn in the center of the screen and concentric, as in the following figure (left). The distance between the circles should be small enough that the Moiré interference is apparent.

    image

    image

  5. Write a method named radial that draws a radial set of line segments as shown in the figure (right), but they should be close enough together to create a Moiré pattern.

  6. Just about any kind of graphical pattern can generate Moiré-like interference patterns. Play around and see what you can create.

«  GridWorld: Part 3   ::   Contents   ::   Input and Output in Java  »