Computer Science 2311
Fall 2009
Laboratory Assignment 9

Handed out: 11/3/09

This is an exercise in using objects and the Java library.


The assignment

This assignment has you create a very simple graphics application. You will create a screen with one button that the user can push. The program will draw disks on the screen.

Your application should paint a disk (a filled circle) with diameter 20 pixels of a random color, and at a random position in the window. The random position should be chosen within limits so that the disk will be completely shown, and will not cover the button. There should be a few color options, such as red, blue, yellow and green. You can choose any set of three or more colors, as long as they are easy to distinguish from one another.

Each time the button is pushed, a color and position should be chosen at random. The old disk should be erased, and the new disk shown.


The Java library

The Java library provides a collection of classes of objects. A class is a type of object. Each class allows you to create as many objects as you need of that class.

For this assignment, you need to make extensive use of the Java library. The assignment tells you everything that you need. But if you want to, you can find out more from http://java.sun.com/j2se/1.6.0/docs/api/index.html. Select a class in the left-hand frame, and you will see the documention in the right-hand frame.


Extending classes

Imagine that you purchase an automobile, with standard features. You decide to add something new, such as a stereo, to it. We will say that you extend the automobile when you add new things.

You use some classes in the Java library by extending them. An object of the extended class has all of the features of the class that it extends, plus any that you add. You can add variables and methods.


Your class heading

The Swing library (javax.swing) has a class called JFrame that manages a window (by handling the frame around the window that can grow and shrink, and that holds the X button, etc.).

You will create a class that extends JFrame. Your version of JFrame will know that it is supposed to put disks and a button inside the frame. Start with the following heading, but select whatever name for your class you like.

  import javax.swing.*;
  import java.awt.*;
  import java.awt.event.*;

  public class Assignment9 extends JFrame
  {
    ...
  }


Screen coordinates

You will be drawing things on the screen at particular points. You indicate a point on the screen by giving is x and y-coordinates.

Screen coordinates are not the same as mathematical coordinates. All coordinates are integers. The (0,0) position is in the upper-left corner of the window, with the x-coordinate getting larger as you move to the right, and the y-coordinate getting larger as you move downward.


Variables

Your object will want to remember some information, such as the point where it has painted a disk and the point where it should paint the next disk. (You give the center point of the disk.) So create variables to hold that information.

Do not declare your variables to be static. (If you have more than one of window frame, then each should remember its own information.) Writing

  int olddiskx, olddisky, newdiskx, newdisky;
inside the class but not inside a method says that the object itself remembers variables olddiskx, olddisky, newdiskx, newdisky.

Create constants telling the width and height (in pixels) of the window. For example, write the following for a 400x400 window.

  private static final int WINDOW_WIDTH  = 400;
  private static final int WINDOW_HEIGHT = 400;
The constants are also written inside the class but not inside any method. (Static means that there is only one copy of them, not a separate copy for each object and final means that you are not allowed to change it; it is a constant.)


A constructor

When you use a class to create objects, you include a special kind of method called a constructor that stores values into an object's variables when the object is created.

Write the constructor as follows so that it sets up the the width, height and title of the window and builds the window. The ... part is discussed below.

  public Assignment9()
  {
    setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
    setTitle("Graphics demo");
    ...
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  }
(The last line, setDefaultCloseOperation..., tells the frame to close the window when you hit the X button at the upper right corner. If you do not include that line, the X button will not do anything.)


Creating the interior of your window.

The JFrame object just manages the outer frame of the window. The interior is called the content pane of the frame, and you can place objects that you manage in the content pane. You will create an object of class JPanel to add to the content frame. You can paint on the JPanel object.

To create the panel, define constants PANEL_WIDTH and PANEL_HEIGHT in your class, telling how large the panel is (in pixels). For example, to make the panel have the same size as the window, say

  private static final int PANEL_WIDTH  = WINDOW_WIDTH;
  private static final int PANEL_HEIGHT = WINDOW_HEIGHT;
Now create the panel object, call it myPanel, and make it have a white background. Then add your panel to the content pane of the frame. Do that by adding the following to the constructor where the ... is, so that the panel is added when the window is created.
  // Build the panel.  It has a white background.  The layout manager
  // object (new FlowLayout()) is responsible for placing things
  // on the panel for you.

  JPanel myPanel = new JPanel();
  myPanel.setLayout(new FlowLayout());
  myPanel.setBackground(Color.white);
  myPanel.setSize(PANEL_WIDTH, PANEL_HEIGHT);

  // The content pane is the interior of the frame.  (In general,
  // you can put more than one object inside the window.  In this
  // program, we only put one object in the content pane.)
  // The content pane also has a white background.  Object
  // new BorderLayout() is responsible for placing objects
  // in the content pane.  Add the panel to at the bottom
  // (SOUTH) side of the pane.

  Container contentPane = getContentPane();
  contentPane.setBackground(Color.white);
  contentPane.setLayout(new BorderLayout());
  contentPane.add(myPanel, BorderLayout.SOUTH);


Painting on the panel

Write a paint method in your class with the following heading.

  public void paint(Graphics canvas)
Notice that it does not include the word static. There is a separate paint method for each object. The heading for paint uses another class, Graphics, that is thought of as a canvas on which you can paint. What you paint on the canvas will show up on the panel. The coordinates for painting are relative to the canvas. So point (0,0) is the upper-left corner of the canvas.

Since your class extends JFrame, before you paint on the canvas you should ask the JFrame object to paint the (white) background on the canvas. Do that using line

  super.paint(canvas);
inside the paint method. For now, that is all you will do.


The main program

Your main program just creates an object of your class and makes it visible, so that you can see it on the screen.

  public static void main(String[] args) 
  {
    JFrame frame = new Assignment9();
    frame.setVisible(true);
  }
Now compile and run your program. All it will do is show the window, with nothing in it. Just close the window.


Drawing a disk

Modify the constructor so that it initializes newdiskx and newdisky to some chosen point. For example, make it be the center of your panel.

Now modify the paint method so that it draws a disk. Statement

  canvas.setColor(Color.red);
tells Graphics object canvas to get out the red paint, and to use it for future painting until told to get another color of paint. Statement
  canval.fillOval(x,y,width,height);
tells Graphics object canvas to paint a filled oval with center (x,y) and the given width and height. To draw a red circle of diameter 20 pixels, you can say
  canvas.setColor(Color.red);
  canvas.fillOval(newdiskx, newdisky, 20, 20);

The paint method will not be performed unless you cause it to be called. To do that, add line

  frame.repaint();
to the end of the main program to repaint the window. Do not call paint directly. You do not have a canvas to paint on. The repaint method creates the canvas, initially holding what the panel holds. (So it is prepainted from the panel.) Then it calls paint to paint more on the canvas. Then it copies what is on the canvas onto your panel.

Try the program now. You should see a disk painted in the window. Again, just close the window.


Painting over a disk

Each time you paint a new disk you will need to paint over the old disk to make it go away. Change paint so that it does the following.

  1. First, paint over the old disk in white, to get rid of it. The old disk has center point (olddiskx, olddisky) and diameter 20.
  2. Next, paint a new disk at point (newdiskx, newdisky), with diameter 20.
  3. Finally, set olddiskx = newdiskx and olddisky = newdisky, telling where the disk has been painted.


Action listeners

Shortly, you will add a button to your class. But you need to say what to do when the button is pushed. First, make your class a kind of ActionListener, meaning that it has a method called actionPerformed that performs actions in response to events such as button pushes. Modify your class heading as follows.

  public class Assignment9 extends JFrame implements ActionListener
Now add a method called actionPerformed that tells where to paint the new disk and repaints.
  public void actionPerformed(ActionEvent e)
  {
    newdiskx += 10;
    newdisky += 10;
    repaint();
  }
The ActionEvent parameter tells what kind of event occurred. Since you will only have one kind of event, you can ignore it.


Adding a button

Now, in your constructor, create a button using the JButton class. Here is an example. It creates a green button labeled move.

  JButton button = new JButton("move");
  button.setBackground(Color.green);
You will want to make the button do something. If you write
  button.addActionListener(this);
then you are saying that, when this button is pushed, the program should perform the method called actionPerformed in the current object.

In the constructor, create the button object and put it on the panel. Statement

  myPanel.add(button);
adds the button to the panel.

Run your program. You should be able to push the button with the mouse and get a new disk drawn.


Choosing random numbers

You can use the Random class in the Java library to get pseudo-random numbers. Add a variable of class Random to your class, and initialize it in your constructor. Statement

  rand = new Random();
creates a new pseudo-random number generator. Only do this once, in the constructor.

To get a pseudo-random integer from 0 to n-1, use rand.nextInt(n). For example, rand.nextInt(4) produces either 0 or 1 or 2 or 3, each equally likely.


Completing the assignment

Your program used to move the disk 10 pixels to the right and down. Modify your program so that it chooses a random position and color for the disk. Some choices of colors are Color.black, Color.blue, Color.red, Color.cyan, Color.magenta, Color.yellow and Color.orange. You can find more colors in the documentation of the Color class. To choose a random color, use an array of colors. Pick a random integer k and choose colors[k] as the color.

Be sure that your disk does not cover the button, and make sure that it stays entirely inside the panel. Think about how you can handle that.


What to turn in

When you have completed your assignment, print it. Then ask either the lab assistant or me to watch a demonstration. We will mark your printout as demonstrated.