CPSC 170 Spring 2003
Program 2: Drawing Shapes
Due Friday, February 28
Write a program that allows the user to create colorful shapes
within a grid by clicking with the mouse. Your program should present
the user with a blank (white) window, which is logically divided into
a grid. When the user clicks on the window, a blue triangle should be drawn
in the square of the grid where the user clicked. When the user clicks
on that area of the grid again, a red circle should replace the blue
the user clicks there again, that
square of the grid should become plain white again. See the demo. (Save it to your
directory, do "tar xzf demo.tgz", cd to the demo directory, and do
These are some of the important components that your program should contain.
Note that this is just a description; you probably should not write
the program in this order. Read the Getting Started section below for
advice on where to begin.
- An abstract Shape class that contains an abstract draw method.
Shape should also contain the shape's x and y coordinates, its color, and
the size of its enclosing square.
- Square, Triangle and Circle classes that extend the Shape class.
Each should have its own draw method; you can use fillRect to draw
the square, fillOval to draw the
circle and fillPolygon to draw the triangle. Be sure you are drawing
the shape inside a grid
square of the given size with the given coordinates as its
upper left-hand corner. For example, consider a grid square whose upper
lefthand corner is at x,y and whose side is size.
A triangle in this square whose base runs
across the bottom and whose top point is in the middle of the
top of the square would have
coordinates (x+size/2, y) for the top point
and (x, y+size) for the lower lefthand corner. You can figure out the lower
- A ShapePanel class that extends JPanel. This is where much of
the real work happens; it contains the paintComponent method and the
MouseListener class. My ShapePanel is 300 pixels in both height and
you can choose whatever size you like.
- In the ShapePanel class, a
two-dimensional array of Shape. This is the "grid"; each element
of the array corresponds to a square on the window.
You will need to decide how big you want your grid (and therefore your array)
to be -- mine is 10 x 10, so combined with my 300 x 300 pixel panel this
gives me 100 squares in the grid, each 30 x 30 pixels.
- A constructor for the ShapePanel class, in which you will
fill the grid array with white Square objects. (Remember
that a Square is a Shape, so this is ok.) The only hard
part about this is figuring out what x and y values (coordinates) to pass
into the Square constructor. Think about it: if your window is 300 pixels
square and you are using a 10 x 10 grid, the upper left-hand
coordinates of the squares on the top row are (0,0), (30,0), (60,0), ...,
(270,0). On the second row they are (0,30),(30,30),(60,30), ..., (270,30).
On the bottom row they are (0,270), (30,270), ..., (270,270). Think about
how to generate these coordinates in terms of the indices of the
grid (0..9 in each direction), and the size of each grid square
(300/10 = 30 pixels).
- A paintComponent method in your ShapePanel class that just runs
through the array and draws each shape in it. Since the shapes know their
locations and colors, paintComponent doesn't need to do anything else.
- A ShapeListener class that implements MouseListener. It needs
a mouseClicked method that figures out which grid square was clicked in,
replaces the shape in there with the next shape in the rotation, and
(Think about how to figure out the grid square... in the example above,
if the user clicks at location (17, 72), what grid square is that in?)
If it's currently a triangle, make it a circle. If it's currently a circle,
make it a square. If it's currently a square, make it a triangle. Pass
the appropriate colors to the shape constructors. Remember that you can
use the instanceof operator to determine if an object is an instance
of a particular class.
- Finally, you will need a driver that creates a JFrame, sets its
DefaultCloseOperation, adds a new ShapePanel to its ContentPane, and
packs and shows it. You can model this on the other drivers we have
used; they have all had the same structure.
To get started, you might want to write just the Shape and Square classes,
plus the constructor and
paintComponent methods for the ShapePanel class. (Of course, you'll need
the driver too.) In the constructor, fill the
grid array with white squares and see if this displays correctly
(the window should be all white). When this works, add the
ShapeListener class and make it replace the square that you click on with
a square of a different color.
When this works, try adding the shapes, thinking about how to get each
to draw correctly, and then rotate them. Voila!