Title: Drawing Basics
Course: CPS 261: Advanced Java Concepts ~ DL & MM MASTER

Drawing Basics

So far we have used Components that knew how to "draw" themselves. It is also possible to do your own thing. The heart of this capability can be found in the Components class --- should be no surprise.

1. The Component class has a method called paint that you can override. When you do, you are passed an instance of the Graphics class that provides many methods that facilitate low level drawing. We will look at these methods, but first let's cover a few more issues.
2. So where is the Component that we are drawing on? An Applet, or a Frame is derived from a Container class which is derived from Component. So if you have a class derived from Applet or Frame, then your class contains a Component class.
3. Overriding the paint method allows you to completely redraw your screen. Normally, paint is called everytime that the Java Runtime System needs to redraw the whole screen. We will look at this issue in more detail later. Also, normally the screen is completely erased just before paint is called.
4. When drawing on your screen, you need to be aware of the coordinate system. Drawing commands often require specification of some x, and y location on the screen. Let's suppose that the Applet or the Frame is given a region that is 500 pixels wide and 200 pixels high to work with. In this case:
  - x=0, y= 0 specifies the upper left corner of the drawable area
  - x=499, y = 0 specifies the upper right corner of the drawable area
  - x=0, y = 199 specifies the lower left corner of the drawable area
  - x=499, y=199 specifies the lower right corner of the drawable area
5. Most drawing happens by making calls to methods on the Graphics class. An instance of the Graphics class is passed into the paint method.
6. Java draws with a single color until a call to setColor is made to switch the color to another color. The set Color takes in an instance of the Color class. The Color class shows up in the java.awt package and has some interesting methods and constructors. It is worthwhile to take a look at the online help for the Color class.
  - One way to get a color class is to use some of the Statically defined constant colors such as:
Color.red, Color.yellow, Color.black, etc.
  - Another way is to think in terms of mixing colors with Red, Green, Blue (RGB mode). There is a constructor that allows you to mix colors by passing numbers that are between 0 and 255:
//mix in some whiteness
Color myLightRed = new Color(255, 150, 150);
  - Another Constructor that can sometimes be useful
Color myColor = new Color(float, float, float);
I will use this to create a random color:
Color myRandom = new Color((float)Math.random(),
(float)Math.random(), (float)Math.random());
  - One last useful constructor:
Color myColor = new Color(int);
This can be handy after converting a hex color input (FF8080) into an integer
7. The Pen color defaults to whatever the last call to setForeground.
8. Methods that start with draw create hollow objects, while methods that start with fill create solid objects. Also the first 4 parameters on these methods are often:
  - starting x
  - starting y
  - width
  - height

Some examples:
drawRectangle(10,12, 20, 50); // (x,y, w, h)
drawOval (10,12, 20, 50);
fillRectangle(10,12, 20, 50);
fillOval(10,12, 20, 50);
9. drawLine draws a line between points (x1,y1) and (x2,y2)
drawLine(x1,y1, x2, y2);
10. drawString draws a Text string that starts at location x, y:
drawString("Some Name", 10, 150);

Simple.java


import java.awt.*;
import java.applet.Applet;

public class Simple extends Applet {

    public void paint(Graphics g) {
        g.drawRect(10,10, 400, 150);

        g.setColor(Color.red);
        g.fillOval(110,35, 200, 100);

        g.setColor(Color.green);
        g.fillRoundRect(160, 60,  100, 50, 10, 10);
        g.drawLine(10, 180, 400, 180);

        g.setColor(Color.blue);
        g.drawString("Clem's Artwork", 10, 175);
    }
}


The Forida.java example below is better example of good artwork. It also uses a few more Graphics methods -- I'm mostly going to encourage you to look these up in online help and play around with them if you want to learn more.

1. drawRoundRect - Similar to drawRect, except that it has 2 extra parameters to specify how much to round the corners.
2. Polygon class - This class provides logic for dealing with Polygons. We aren't using much from this class, but look it up to see what it contains --- some neat routines in it.
3. drawPolygon - this method draws a Polygon
4. drawArc - Useful routine for drawing partial circlular arcs. There is also fillArc.

Florida.java


import java.awt.Graphics;
import java.awt.Polygon;

public class Florida extends java.applet.Applet {

    public void paint(Graphics screen) {

        // Draw the big box around the whole applet
        screen.drawRect(2, 2, 345, 345);

        // Draw the Florida text with a line under it and
        // surrounded by a rounded rectangle

        screen.drawString("Florida", 185, 75);
        screen.drawLine(185,80,222,80);
        screen.drawRoundRect(182,61,43,24,10,8);

        // Draw Florida Boundary
        int x[] = { 10, 234, 253, 261, 344, 336, 295, 259, 205, 211,
            195, 191, 120, 94, 81, 12, 10 };
        int y[] = { 12, 15, 25, 71, 209, 278, 310, 274, 188, 171, 174,
            118, 56, 68, 49, 37, 12 };
        int pts = x.length;
        Polygon poly = new Polygon(x, y, pts);
        screen.drawPolygon(poly);

        // Mickey Mouse
        screen.fillOval(235,140,15,15);
        screen.fillOval(225,130,15,15);
        screen.fillOval(245,130,15,15);

        // Draw the Waves
        for (int ax = 50; ax < 150; ax += 10)
            for (int ay = 120; ay < 320 ; ay += 10)
                screen.drawArc(ax, ay, 10, 10, 0, -180);
    }
}




ShapesDemo.java

This Applet provides a gallery of Graphics class methods. Again, I'm going to leave it upto you to look these up in online help and play with them to see what they do.

One interesting property of this applet is that it automatically resizes itself to fit the size allowed for it. If you make somewhat small, the text begins to overlap. Build this on your web site and change the width and height (make them larger) to see how this applet automatically grows.

This is done with the following logic:

The method getSize returns the size of the Container in an instance of a Dimension class. The Dimension class has values of width and height which can return the Container sizes in pixels.

Using the width and height, this Applet automatically computes its coordinates to fit all objects into the size allotted to it.

Also note that we are using a different drawPolygon method than we used in the Florida.java example. This drawPolygon class avoids creating the Polygon class and just takes in an array of points.


import java.awt.*;
import java.applet.Applet;

/*
 * This displays a framed area containing one of
 * each shape you can draw.
 */

public class ShapesDemo extends Applet {
    final static int maxCharHeight = 15;
    final static Color bg = new Color(230, 230, 230);
    final static Color fg = Color.black;
    final static Color fg3D = new Color(180, 180, 180);

    public void init() {
        //Initialize drawing colors
        setBackground(bg);
        setForeground(fg);
    }


    public void paint(Graphics g) {
        Dimension d = getSize();
        int x = 5;
        int y = 7;
        int gridWidth = d.width / 7;
        int gridHeight = d.height / 2;
        int stringY = gridHeight - 7;
        int rectWidth = gridWidth - 2*x;
        int rectHeight = stringY - maxCharHeight - y;


    // Draw the border.
        g.setColor(fg3D);
        g.draw3DRect(0, 0, d.width - 1, d.height - 1, true);
        g.draw3DRect(3, 3, d.width - 7, d.height - 7, false);
        g.setColor(fg);

        // drawLine(x1, y1, x2, y2)
        g.drawLine(x, y+rectHeight-1, x + rectWidth, y);
        g.drawString("drawLine()", x, stringY);
        x += gridWidth;

        // drawRect(x, y, w, h)
        g.drawRect(x, y, rectWidth, rectHeight);
        g.drawString("drawRect()", x, stringY);
        x += gridWidth;

        // draw3DRect(x, y, w, h, raised)
        g.setColor(fg3D);
        g.draw3DRect(x, y, rectWidth, rectHeight, true);
        g.setColor(fg);
        g.drawString("draw3DRect()", x, stringY);
        x += gridWidth;

        // drawRoundRect(x, y, w, h, arcw, arch)
        g.drawRoundRect(x, y, rectWidth, rectHeight, 10, 10);
        g.drawString("drawRoundRect()", x, stringY);
        x += gridWidth;

        // drawOval(x, y, w, h)
        g.drawOval(x, y, rectWidth, rectHeight);
        g.drawString("drawOval()", x, stringY);
        x += gridWidth;

        // drawArc(x, y, w, h)
        g.drawArc(x, y, rectWidth, rectHeight, 90, 135);
        g.drawString("drawArc()", x, stringY);
        x += gridWidth;

        // drawPolygon(xPoints, yPoints, numPoints)
        int x1Points[] = {x, x+rectWidth,  x,            x,              x+rectWidth};
        int y1Points[] = {y, y+rectHeight, y+rectHeight, y+rectHeight/2, y};
        g.drawPolygon(x1Points, y1Points, x1Points.length);
        g.drawString("drawPolygon()", x, stringY);

        // NEW ROW
        x = 5;
        y += gridHeight;
        stringY += gridHeight;

        // drawPolyline(xPoints, yPoints, numPoints)
        // Note: drawPolygon would close the polygon.
        int x2Points[] = {x, x+rectWidth, x, x+rectWidth};
        int y2Points[] = {y, y+rectHeight, y+rectHeight, y};
        g.drawPolyline(x2Points, y2Points, x2Points.length);
        g.drawString("drawPolyline()", x, stringY);
        x += gridWidth;

        // fillRect(x, y, w, h)
        g.fillRect(x, y, rectWidth, rectHeight);
        g.drawString("fillRect()", x, stringY);
        x += gridWidth;

        // fill3DRect(x, y, w, h, raised)
        g.setColor(fg3D);
        g.fill3DRect(x, y, rectWidth, rectHeight, true);
        g.setColor(fg);
        g.drawString("fill3DRect()", x, stringY);
        x += gridWidth;

        // fillRoundRect(x, y, w, h, arcw, arch)
        g.fillRoundRect(x, y, rectWidth, rectHeight, 10, 10);
        g.drawString("fillRoundRect()", x, stringY);
        x += gridWidth;

        // fillOval(x, y, w, h)
        g.fillOval(x, y, rectWidth, rectHeight);
        g.drawString("fillOval()", x, stringY);
        x += gridWidth;

        // fillArc(x, y, w, h)
        g.fillArc(x, y, rectWidth, rectHeight, 90, 135);
        g.drawString("fillArc()", x, stringY);
        x += gridWidth;

        // fillPolygon(xPoints, yPoints, numPoints)
        int x3Points[] = {x, x+rectWidth,  x,            x,                x+rectWidth};
        int y3Points[] = {y, y+rectHeight, y+rectHeight, y + rectHeight/2, y          };
        g.fillPolygon(x3Points, y3Points, x3Points.length);
        g.drawString("fillPolygon()", x, stringY);
    }
}




Exercises

1. Parametrizing the Background and Foreground Colors
Modify the Florida Drawing applet to have a background and a foreground color that is set by Parameters in the html files. Have the colors specified as a hexidecimal RGB(Red, Green, Blue) number. For example, Red is 0xFF0000, while blue is 0x0000FF. You probably want to use the version of parseInt that takes 2 parameters.
2. Simple Nested Ellipses
The idea here is to start out simple and incrementally grow into a more complicated applet.
  - Create an ellipse that is filled in with the color red.
  - Using getSize, find out how big your applet is. Using this information make your ellipse expand to the size of the applet.
  - This time create a for loop that successively draws smaller ellipses having the same center. Have the even iterations fill the ellipse with red and and odd iterations fill the ellipse with blue.
3. Modify the Spots Program
Modify the Spots Program to provide the following functionality:
  - Make the size of the spots random. Have the minimum size and the maximum size settable through parameters in the html file
  - Make the shape of the spots configurable through parameters.. In otherwords, you can use square spots, rectangular spots, etc.
  - Create another version of your spots program that makes the shapes randomly selected on each click.
4. Stick Man
  - Draw a simple stick man. Use drawLine, drawOval (or fillOval) and whatever other Graphics class routines you want. Make the stick man with at least 2 colors.
  - Use copyArea to replicate your stick man multiple times. If you want, you can make what looks like wallpaper this way by using a for loop.
5. Open Ended Art
Create any art project in an Applet that happens to be of interest to you.
6. Draw a Clock
Create a clock drawing. You can keep it simple with circles and lines. Feel free to use color for the different parts of the clock. You might want to have the colors of the clock cofigurable by using parameters in the html file. One of my previous students got carried away with this exercise and gave me the following applet:
Fancy Clock
7. Simple Click and Draw Exercise
In this exercise, put together a simple applet that draws a new line with each mouse click. On the first click , you just need to save the clicked location. For the second, third, fourth, etc. clicks you should draw the following lines:
  - line connecting first click to the second click
  - line connecting second click to the third click
  - line connecting third click to the fourth click
  - etc.
Your program should save it's points so that if you navigate to another page and come back, your drawing is still in place. Take a look at the Dyanamic Drawing set of notes and the Spots examples for clues.
8. Bar Chart Exercise
  - Make an applet named AChart that provides simple bar chart functionality. Your applet should be driven by input parameters. Take a look at AGraph3.java. Your AChart should be able to handle the same input as AGraph3.java. In fact the output should be similar to AGraph3.java except that bar charts are drawn instead of a Graph.
  - Put actual numbers on the far right side of each bar to indicate the actual x value represented.
  - Put some labels on the axis. For example, if your bar chart rectangles are horizontal, then on the far left hand side it would be nice to label each bar that is drawn. See some of the examples below to demonstrate some Graphing programs:
Graphing Examples

Last Updated: December 6, 2002 11:22 AM