Skip to main content

PennDraw.java


PennDraw Reference Page

PennDraw is an expanded ersion of StdDraw from Sedgewick and Wayne’s Introduction to Programming in Java: An Interdisciplinary Approach. It supports everything that StdDraw supports, plus additional drawing and animation commands.


Downloading and Using PennDraw

To use PennDraw, save PennDraw.java to the same folder as your program. Once you add it to your folder, you should open it up and compile it. If you are using Codio, if the filetree has the cis110.jar file in your filetree, you do not need to save PennDraw.java as it is already provided for you.


Getting Started: A Simple Program

Here’s a simple program that draws a line and a point:

public class PennDrawTest {
    public static void main(String[] args) {
        PennDraw.line(0, 0, 1, 1);
        PennDraw.point(0, 1);
    }
}

Why aren’t (0, 0) and (1, 1) at the actual corners of the window? Most CIS 110 assignments that involve drawing will require you to keep your drawing within the “unit square” defined by the corners (0, 0) and (1, 1). The margin that PennDraw adds makes it easy to visually verify that you stay inside this square: just draw the unit square (PennDraw.square(0.5, 0.5, 0.5); — see below) and make sure your drawing is completely inside it.


Window Size and Scale

By default, the PennDraw window is 512×512 pixels. To change this, use

PennDraw.setCanvasSize(width, height);

You can also change the window’s coordinate system, which can make it much easier to compute the coordinates for your shapes:

PennDraw.setXscale(left, right);
PennDraw.setYscale(bottom, top);
PennDraw.setScale(left/bottom, right/top);
PennDraw.setScale();

Trying out the scale functions:

public class PennDrawScaleTest {
    public static void main(String[] args) {
        PennDraw.setXscale(0, 2);
        PennDraw.line(0, 0, 1, 1);
        PennDraw.point(0, 1);
    }
}

Point/Line Thickness and Color

These calls adjust the line thickness:

PennDraw.setPenRadius();
PennDraw.setPenRadius(radius);
PennDraw.setPenWidthInPoints(width);

You can also change the line color:

PennDraw.setPenColor();
PennDraw.setPenColor(color);
PennDraw.setPenColor(red, green, blue);
PennDraw.setPenColor(red, green, blue, alpha);

Trying out line thickness and color functions:

public class PennDrawPenTest {
    public static void main(String[] args) {
        PennDraw.line(0, 0, 1, 1);
        PennDraw.setPenColor(PennDraw.BLUE);
        PennDraw.setPenRadius(0.005);
        PennDraw.line(1, 0, 0, 1);
    }
}
PennDrawPenTest.java:5: error: cannot find symbol
PennDraw.setPenColor(PennDraw.blue);
                             ^
        symbol:   variable blue
        location: class PennDraw

This is a compiler error, and is roughly analagous to a spelling or grammar error in English. Moral: CAPITALIZATION MATTERS!!!

PennDrawPenTest.java:5: error: no suitable method found for setPenColor(double,double,double,double)
        PennDraw.setPenColor(0.5, 0.5, 0.5, 0.5);
                ^
Exception in thread "main" java.lang.IllegalArgumentException: amount of red must be between 0 and 255
        at PennDraw.setPenColor(PennDraw.java:435)
        at PennDrawPennTest.main(PennDrawPennTest.java:5)

This is Java’s way of saying that you have specified a color value that looks ok at first sight (everything is whole numbers), but is in fact bogus. It’s analagous to an English sentence that is grammatically correct and made up of real words, but is total gibberish. (“Green blackbirds cha-cha solemnly from dawn to Australia.”)


Clearing the Window

To clear the window, use: PennDraw.clear();

PennDraw.clear(color);
PennDraw.clear(red, green, blue);
PennDraw.clear(red, green, blue, alpha);

PennDraw.clear() erases everything on the screen and makes the entire window background white. If you want to set the window background to a different color, you can specify the color by name, or as red, green, and blue values, just like line colors. You can even specify transparency on your background color, in which case whatever was already drawn on the window will show through.


Points and Lines

Draw points and lines using:

PennDraw.point(x, y);
PennDraw.line(xstart, ystart, xend, yend);

x, y, xstart, ystart, xend, and yend are the coordinates of the point and the start and end of the line. The sample programs in the previous section illustrate their use.

How do I draw a bunch of one-pixel points really fast? When you draw a point, you are actually drawing a little circle whose size depends on the current line thickness. If you want the point to be exactly one pixel in size, you should first call PennDraw.setPenRadius(0);. This will ensure the points are exactly one pixel in size and get draw really fast. (The speed only matters when you want to animate hundreds of points at once.)


Squares and Circles

Draw squares and circles using:

PennDraw.square(xcenter, ycenter, halfWidth);
PennDraw.square(xcenter, ycenter, halfWidth, angle);
PennDraw.filledSquare(xcenter, ycenter, halfWidth);
PennDraw.filledSquare(xcenter, ycenter, halfWidth, angle);

PennDraw.circle(xcenter, ycenter, radius);
PennDraw.filledCircle(xcenter, ycenter, radius);

xcenter and ycenter are the coordinates of the center of the square, not one of its corners! angle gives the amount of counter-clockwise rotation in degrees The PennDraw.square() functions draw an outline in the current line color. The PennDraw.filledSquare() functions draw a square filled with the current line color.

Sample square program:

public class PennDrawSquareTest {
    public static void main(String[] args) {
        // solid black square centered at (.5, .5)
        // with sides of length .6 (half-width of .3)
        PennDraw.filledSquare(0.5, 0.5, 0.3);

        // blue square outline centered at (.7, .3)
        // with sides of length .4
        // rotated 30 degrees counter-clockwise
        PennDraw.setPenColor(PennDraw.BLUE);
        PennDraw.square(.7, .3, .2, 30);
    }
}

Rectangles and Ellipses

Draw rectangles using:

PennDraw.rectangle(xcenter, ycenter, halfWidth, halfHeight);
PennDraw.rectangle(xcenter, ycenter, halfWidth, halfHeight, angle);
PennDraw.filledRectangle(xcenter, ycenter, halfWidth, halfHeight);
PennDraw.filledRectangle(xcenter, ycenter, halfWidth, halfHeight, angle);

PennDraw.ellipse(xcenter, ycenter, halfWidth, halfHeight);
PennDraw.ellipse(xcenter, ycenter, halfWidth, halfHeight, angle);
PennDraw.filledEllipse(xcenter, ycenter, halfWidth, halfHeight);
PennDraw.filledEllipse(xcenter, ycenter, halfWidth, halfHeight, angle);

xcenter and ycenter are the coordinates of the center of the rectangle, not one of its corners! angle gives the amount of counter-clockwise rotation in degrees The PennDraw.rectangle() functions draw an outline in the current line color. The PennDraw.filledRectangle() functions draw a square filled with the current line color.

Sample rectangle program:

public class PennDrawRectangleTest {
    public static void main(String[] args) {
        // solid black square centered at (.5, .5)
        // with sides of length .6 (half-width of .3)
        PennDraw.filledRectangle(0.5, 0.5, 0.3, .15);

        // blue square outline centered at (.7, .3)
        // with sides of length .4
        // rotated 30 degrees counter-clockwise
        PennDraw.setPenColor(PennDraw.BLUE);
        PennDraw.rectangle(.7, .3, .2, .1, 30);
    }
}

Arcs, Closed Arcs, and Pies

PennDraw support circular arcs—arcs that are part of a circle. Specify them by given the center and radius of a circle, and the start and end angles of the arc you want to draw. You can also close the arc with a straight line or chord (a “closed arc”), or by connected the ends of the arc back to the center of the circle (a “pie”):

PennDraw.arc(x, y, r, startAngle, endAngle);

PennDraw.closedArc(x, y, r, startAngle, endAngle);
PennDraw.filledArc(x, y, r, startAngle, endAngle);

PennDraw.pie(x, y, r, startAngle, endAngle);
PennDraw.filledPie(x, y, r, startAngle, endAngle);

Sample arc program:

public class PennArcTest {
    public static void main(String[] args) {
        // black arc
        PennDraw.arc(0.15, 0.6, 0.3, 10, 100);

        // blue closed arc and filled arc
        PennDraw.setPenColor(PennDraw.BLUE);
        PennDraw.closedArc(0.15, 0.3, 0.3, 10, 100);
        PennDraw.filledArc(0.15, 0.0, 0.3, 10, 100);

        // red pie and filled pie
        PennDraw.setPenColor(PennDraw.RED);
        PennDraw.pie(0.65, 0.6, 0.3, 10, 100);
        PennDraw.filledPie(0.65, 0.1, 0.3, 10, 100);
    }
}

Polylines and Polygons

Polygons and polylines are closely related: for both you specify a list of coordinates that are connected in order by straight line segments. The difference is that a polygon connects the last point back to the first one to create a closed shape. There are two forms for specifying the points, and you can use whichever form is most convenient in your program.

Form 1:

PennDraw.polyline(x1, y1, x2, y2, x3, y3, ...);
PennDraw.polygon(x1, y1, x2, y2, x3, y3, ...);
PennDraw.filledPolygon(x1, y1, x2, y2, x3, y3, ...);

In form 1, the arguments are the alternating x and y coordinates of the points. You can specify as many points as you like.

Form 2:

PennDraw.polyline(xcoordsArray[], ycoordsArray[]);
PennDraw.polygon(xcoordsArray[], ycoordsArray[]);
PennDraw.filledPolygon(xcoordsArray[], ycoordsArray[]);

In form 2, you specify two arrays of values. The first is a list of the x-coordinates of all the points, and the second is the list of all the y-coordinates.

Sample polyline/polygon program:

public class PennArcTest {
    public static void main(String[] args) {
        // three-segment (four-point) black polyline
        PennDraw.polyline(0, 0, 0.25, 0, .25, 1, 0, 1);

        // blue, five-sided polygon
        PennDraw.setPenColor(PennDraw.BLUE);
        double[] xcoords = { 0.5, 1, 1  , 0.75, 0.5 };
        double[] ycoords = { 0  , 0, 0.7, 1   , 0.7 };
        PennDraw.polygon(xcoords, ycoords);
    }
}

Images

Drawing images is quite easy:

PennDraw.picture(xcenter, ycenter, filename);
PennDraw.picture(xcenter, ycenter, filename, angle);
PennDraw.picture(xcenter, ycenter, filename, width, height);
PennDraw.picture(xcenter, ycenter, filename, width, height, angle);

Text

Drawing Text:

PennDraw.text(x, y, text);
PennDraw.text(x, y, text, angle);

PennDraw.textLeft(x, y, text);
PennDraw.textLeft(x, y, text, angle);

PennDraw.textRight(x, y, text);
PennDraw.textRight(x, y, text, angle);

For example:

PennDraw.text(0.4, 0.2, "abc", 30);

Changing the font and size:

PennDraw.setFont(fontName);
PennDraw.setFont(fontName, pointSize);
PennDraw.setFontSize(pointSize);

PennDraw.setFontPlain();
PennDraw.setFontBold();
PennDraw.setFontItalic();
PennDraw.setFontBoldItalic();

Finding out what font names you can use:

The available fonts vary system by system, and it can be a little difficult to figure out what the names to give setFont(). We provide the following function to help you:

PennDraw.listFonts();


Animation

PennDraw provides three functions for creating animations:

PennDraw.disableAnimation();
PennDraw.enableAnimation(frameRate);
PennDraw.advance();

What about StdDraw.show()? The StdDraw library on which PennDraw is based uses a function called StdDraw.show() for animation. We have split this into the three functions above for clarity. PennDraw supports StdDraw’s show() function to make it easy to convert programs, but we recommend against using it.


Keyboard and Mouse

PennDraw has very basic support for keyboard and mouse input. It is much less powerful than most user interface libraries provide, but also much simpler.

To read in everything a user has typed so far, you need to call PennDraw.nextKeyTyped() once for each character the user has typed. The following example builds a String of everything the user has typed so far, then prints it out:

while (true) {
    String s = "";
    if (PennDraw.hasNextKeyTyped()) {  // make sure there is keyboard input to process
        s += PennDraw.nextKeyTyped();  // read in one character of keyboard input and add it to the end of s
    }
    System.out.println(s);             // print out the string
}

Sometimes you want to ignore everything the user has typed, and only pay attention to what gets typed going forward. To do this, you need to read in everything the user has typed and do nothing with it:

while (PennDraw.hasNextKeyTyped()) {  // as long as there is keyboard input to process
    PennDraw.nextKeyTyped();          // read in one character of keyboard input, but don't save it
}