SUNY Geneseo Department of Computer Science
CSci 240, Spring 2007
Prof. Doug Baldwin
Due Tuesday, January 23
In order to do this exercise, you will need to know how to use some Java programming environment, and you will need to know the basics of graphics in Java.
I will walk through setting up, editing, and running a Java program with XCode during the lab session for anyone who is interested. If you prefer to use some other programming environment, you are welcome to do so, although you will be more on your own to learn how to use that environment.
The ultimate product in this exercise is a program that draws a certain pattern in a window. You will therefore need to know something about windows and graphics in Java to write this program. You can read about the various graphics classes in detail in the Java library documentation, but the following is a summary of what you should need for this exercise.
Computer graphics is generally a matter of making the computer draw lines, rectangles, and similar shapes in a window on the monitor. You describe these shapes relative to a two-dimensional coordinate system -- for example, to draw a line you would say where its endpoints are in this coordinate system, and the computer would then draw the line between those points.
Coordinates are measured in units of pixels, where a pixel is the smallest point on the screen that can be colored. A typical monitor today is on the order of 1000 pixels wide and high, while typical windows are several hundred pixels wide and high. Coordinate values are always integers.
In every window coordinate system I have ever seen, one axis runs horizontally across the window, and the other runs vertically down the window. Coordinates on the horizontal axis run from 0 at the left edge of a window to the window's width in pixels, minus one, on the right. Vertical coordinates run from 0 at the top to the window's height minus one at the bottom. Note that vertical coordinates increase down, contrary to coordinate systems you are used to from mathematics; point (0,0) is the upper left corner of the window.
The Java library class JFrame
represents a window on your monitor.
JFrame
is defined in the javax.swing
package, so before you do anything with a JFrame
you need to import that package. If you want to change how the window behaves when closed (via the setDefaultCloseOperation
message, described below), you will also need to import the WindowConstants
interface. Thus, statements such as
import javax.swing.JFrame;
import javax.swing.WindowConstants;
should appear near the beginning of any file that contains code that uses JFrame
.
JFrame
has a constructor that takes the window's title (a string) as its only parameter. For example
JFrame window = new JFrame( "A Sample Window" );
This constructor (and all other JFrame
constructors) create JFrame
objects with a default size, which is not necessarily the size you will want (it's often very small). To change a JFrame
object's size, send it a setSize
message, with the desired width as the first parameter and the desired height as the second parameter. Width and height are measured in pixels. For example, to resize JFrame
window
to be 500 pixels wide by 200 high, use the statement
window.setSize( 500, 200 );
The JFrame
constructors initialize windows so that they are not visible. This allows you to size and otherwise adjust a JFrame
to look the way you want it to before it appears as a window on the screen, but sooner or later you will need to make the window visible. To do this, send the window a setVisible
message with parameter true. For example...
window.setVisible( true );
By default, closing a JFrame
makes the window disappear but doesn't do anything else. To change this behavior, send the JFrame
a setDefaultCloseOperation
message. This message technically takes an integer that encodes the action to take when the window closes as its parameter. Fortunately, programmers needn't know what integers stand for what actions, because a set of predefined constants stores the possible values. These constants are part of the Java library's WindowConstants
interface. One particularly popular one is EXIT_ON_CLOSE
, which indicates that the program that created a window should exit when that window is closed. For example, a program that wanted to exit when JFrame
window
closed would contain the statement
window.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE );
in the code that sets up the window.
If you want to draw a picture in a JFrame
, you need to put an object that can display the picture into the JFrame
-- JFrame
objects cannot display pictures (or much of anything else) by themselves. The Java library provides a class named Canvas
for just this purpose. A Canvas
is basically a region that contains some drawing in a window. The most important message that Canvas
objects handle is paint
, which causes a Canvas
to draw its drawing. This way of drawing the drawing implies that each drawing corresponds to a different kind of Canvas
, since each drawing is produced by different code in the paint
method. Thus, in order to draw a drawing of your own design, you need to define a subclass of Canvas
with a paint
method that draws your drawing.
Note that paint
messages are sent to Canvas
objects automatically, by the Java runtime system, when the runtime system thinks the contents of the Canvas
need to be (re)drawn -- for example, when the JFrame
containing the Canvas
becomes visible, when it is resized, etc. Therefore you will never write a statement that sends a paint
message.
The Canvas
class is defined in the java.awt
package, so before you can define a subclass of Canvas
, you need to import Canvas
from that package. In order to write a paint
method for the subclass you will also need to import the Graphics
class from java.awt
. Statements such as
import java.awt.Canvas;
import java.awt.Graphics;
should therefore appear near the beginning of any file that defines a subclass of Canvas
.
Here is an example of a complete but minimal subclass of Canvas
. This subclass represents pictures consisting of a single flat line. Note that the paint
method receives a Graphics
object as its parameter. This object is what actually does graphics operations; the Graphics
class is described in the next section of this handout.
import java.awt.Canvas;
import java.awt.Graphics;
class SimpleCanvas extends Canvas {
public void paint( Graphics g ) {
g.drawLine( 10, 10, 100, 10 );
}
}
Once you have a subclass of Canvas
that can draw what you want, you need to create an instance of it and put that instance into some JFrame
. The message that puts objects into a JFrame
is add
, which takes the object being put into the JFrame
as its only parameter. Thus, for example, if you wanted to display a flat line (via a SimpleCanvas
object) in JFrame
window
, you would have a statement such as
window.add( new SimpleCanvas() );
in the code that sets up window
.
You probably noticed that the paint
message receives a Graphics
object as its parameter. Graphics
is a class that represents objects that know how to do simple graphics on Canvas
objects (and on other things that can appear in windows).
Each Graphics
object draws relative to a pixel coordinate system for the Canvas
on which it is drawing -- i.e., a coordinate system whose (0,0) point is the upper left corner of the Canvas
, and that measures in units of pixels. In working with this coordinate system, it is sometimes useful to know what the maximum X and Y coordinates are, i.e., the width and height of the Canvas
. You can discover these values by sending the Canvas
getWidth
and getHeight
messages. Both messages return the width or height of the Canvas
in pixels, and neither has any parameters. Remember, however, that the actual visible coordinates range from 0 to one less than the width or height of the Canvas
. Thus, for example, a paint
method that needed to know the bounds on the area it could draw in might start like this:
public void paint( Graphics g ) {
int maxX = this.getWidth() - 1;
int maxY = this.getHeight() - 1;
... etc. ...
The most important message to Graphics
objects for this exercise will be drawRect
, which makes a Graphics
object outline a rectangle. This message takes four parameters: the X and Y coordinates of the rectangle's upper left corner, and the rectangle's width and height. For example, to make Graphics
object g
draw a rectangle 10 pixels wide and 50 pixels high, starting at (3,4), you would say
g.drawRect( 3, 4, 10, 50 );
You can do this exercise with drawRect
as the only message you send to Graphics
objects. However, here are brief outlines of some other messages that might just be fun to play with:
drawLine
draws a line between two points. The parameters are the coordinates of the two points. For example
g.drawLine( x1, y1, x2, y2 );
fillRect
fills a rectangle with color, as opposed to just drawing its outline. The parameters are the same as those to drawRect
. For example
g.fillRect( x1, y1, width, height );
drawOval
and fillOval
are analogous to drawRect
and fillRect
, except that they outline or fill an oval instead of a rectangle. Parameters are the upper left corner, width, and height of an invisible rectangle that just fits around the oval.
setColor
sets the color in which future drawing will be done. The parameter is a Color
object that specifies the desired color. See the Java library documentation for class Color
to learn about Color
objects.
Write a Java program that opens a window on the monitor and displays a certain picture (described below) in it. The program should provide some way for users to stop it, but it needn't provide any other user interaction.
The picture your program should display is really an abstract pattern, drawn in a rectangular region of the window. Suppose the coordinates of the upper-left corner of the region are (x1,y1) and the coordinates of the lower right corner are (x2,y2). Then the pattern is defined as follows:
Here is an example of this pattern. Note that this is a fairly small example, your program should be able to draw patterns of whatever size your Canvas
is.
This is a big exercise if you try to tackle it as one monolithic task. However, if you break it into small steps, it's not so bad (and what questions you have about each step provides a good gauge of what you already know about Java programming and what I should review). I suggest the following steps:
JFrame
in the "Background" section for information on how to open windows. Also in this step, you can write the code that sets any features you want the window to have, e.g., its height or width, whether the program exits when the window closes, etc.Canvas
in order to draw the pattern (see the discussion of Canvas
in the "Background" section for what the Canvas
class is and why you need a subclass of it). So extend the program to include a minimal Canvas
subclass, and put an instance of this subclass in the program's JFrame
. Don't make the Canvas
subclass draw the whole pattern yet, just have it draw something simple like a single line for now. Canvas
subclass by making it draw the actual pattern. Hint: it may be easiest to do this if you write an auxiliary method in your subclass that does most of the drawing, and just have paint
call this auxiliary method with appropriate parameters. I will grade this exercise in a face-to-face meeting with you. Make an appointment to meet with me at some time convenient for you, as long as that time is before the end of the due date above. Meetings only need to be 15 minutes long. You can make an appointment by signing up on the copy of my schedule on the bulletin board outside my office.
I would like to read and run your program during our meeting. To do this, you can either bring the program to my office on a laptop computer, or we can go to a lab during the meeting.