CPSC 170 Lab 3
More Listeners, GUIs, & Polymorphism
As usual, create a lab3 subdirectory for today's lab, open this
document in FireFox, and start emacs.
More Mouse Events
- The file Circles.java sets up a GUI that
creates and draws a circle as defined in Circle.java
of random size and color at each mouse press
Each
circle replaces the one before it. The code to handle the mouse
press and do the drawing is in
CirclePanel.java.
Save these files to your directory,
compile them and run them and experiment with the GUI.
Then modify these files as described below.
- This program creates a new circle each time -- you can
tell because each circle is a different color and
size. Write
a method void move(Point p) for your Circle class that takes a Point
and moves the circle so its center is at
that point. Now modify your CirclesListener class (defined inside
CirclePanel) so that
instead of creating a new circle every time the user presses the mouse,
if a circle already exists it moves the existing circle to the point where
the user pressed (the "presspoint"). If
no circle exists, a new one should be created at the presspoint.
So now a circle of the same color and size should
move around the screen.
- Write a method boolean isInside(Point p) for your
Circle class that takes a Point and
tells whether it is inside the circle. A point is inside the
circle if its distance from the center is less than the radius.
Recall that the distance between two points (x1,y1) and (x2,y2) is
sqrt((x2-x1)2+(y2-y1)2.
- Now modify the mousePressed method
of CirclesListener so that the GUI
behaves as follows:
- If there is no circle (i.e., it is null) and the user presses anywhere,
a new (random) circle should be drawn at the presspoint.
- If there is a circle on the screen and the user presses
inside that circle,
the circle should go away. (Hint: To make the circle go away, set it to
null and repaint.)
- If there is a circle on the screen and the user presses
somewhere else,
the circle should move to that point (no change from before).
So the logic for mousePressed should look like this:
if there is currently no circle
create a new circle at the presspoint
else if the click is inside the circle
make the circle go away
else
move the circle to the presspoint
repaint
- Add bodies for the mouseEntered and mouseExited
methods so that when the mouse enters the JPanel
the background turns white,
and when it exits the background turns blue. Remember that you can set the
background color with the setBackground method.
-
Now modify the code in CirclePanel.java so that a circle is drawn
when the user presses a mouse, but the user can drag it around as long
as the mouse button is depressed. If the mouse button is released and
then pressed again, it deletes or moves the circle as before.
You will need to make the following changes:
- In the CirclePanel constructor, make the CirclesListener object
listen for both mouse events and mouse motion events. Don't create
two separate listeners -- use the same
object for both.
- Make the CirclesListener class implement the MouseMotionListener
interface in addition to the MouseListener interface. This requires two
steps:
- Note in the header that CirclesListener implements MouseMotionListener.
- Add bodies for the two MouseMotionListener methods,
mouseDragged and mouseMoved. In mouseDragged,
simply move the circle to the point returned by the getPoint method of
the MouseEvent and repaint. (Remember that you already wrote a move() method
for the Circle class.) Provide an empty body for mouseMoved.
Print CirclesListener.java and Circle.java to
turn in.
- The files RubberLines.java and
RubberLinesPanel.java implement the code
listings (7.20, 7.21) from your textbook. Download these files and execute
them to see how they work.
- Confirm your understanding of the "super" reference in Paint component
by commenting it out and observing the differences.
- Implement your strategy from prelab for retaining and drawing
all the lines specified by the user.
-
Copy the card class and the PileOfCards class from your lab2 directory.
At the command prompt if you are in the lab3 directory, you can type
cp ../lab2/card.java .
Note: When you open these files in Eclipse, don't forget to change the package name
Download the file TwoCardPanel.java and
CardGame.java and
Run the CardGame program to understand how it works (It is pretty similar to
last week, except there are two cards)
We would like to attach a mouse listener to each of the JLabels
so that when
the mouse clicks on the picture of a card, the program prints out the name of
the card. This may seem easy at first, but there are a couple of hurdles that
you will have to overcome to make this work nicely. Here is the general
idea.
- In the CardPanel constructor, make the "CardListener" object and add it
to both of the JLabels. In this case, you shouldn't create two separate
listeners -- use the same object for both.
- In the CardPanel class, create an inner class called CardListener that
implements a Mouse Listener.
- In the mouseClicked method, determine which of the cards was pressed
(hint: getSource) and print it out.
What is wrong with this solution? Try to figure out the problem
before you implement it. If you can't, that is ok too, try
implementing it and see where it goes wrong.
How do you fix the problem? See if you can think of a solution and then talk
to me or the lab assistant to discuss your ideas.
Checkboxes and Radio Buttons
Up until now, you hav been creating simple GUIs with panels, textboxes and
buttons. Recall that these programs used ActionListeners to carry out
certain actions when a button was pressed. In today's exercise you will see
two new GUI components (checkboxes and radio buttons)
along with their listeners (ItemListeners and ActionListeners respectively).
The files StyleOptions.java and
StyleOptionsPanel.java
are adapted from Listings 5.22 and 5.23 of the text. (A variable
fontSize is used rather than an integer literal in various instances
and the variable style is an instance variable rather than local to the
itemStateChanged method). Save these files to your directory and
run StyleOptions.java to see how it works. This is the driver;
StyleOptionsPanel.java contains the code for the GUI.
Now you will add a set
of 3 radio buttons to let the user choose among three font sizes. The
method of adding the radio buttons will be very similar to that in the
QuoteOptionPanel class (Listing 5.25 of the text), so study this example
before you continue.
Do the following to add the radio buttons to the GUI:
- Declare three objects small, medium, and
large of type JRadioButton.
- Instantiate the button objects labeling them "Small Font," "Medium Font,"
"Large Font." Initialize the large font button to true. Set the
background color of the buttons to cyan.
- Instantiate a button group object and add the buttons to
it.
- Radio buttons produce action events so you need to add an inner
class (name it SizeListener) to implement ActionListener and
listen for radio button clicks. The code for actionPerformed
can be similar to that in the QuoteListener in Listing 5.25. (Or if you prefer,
you can use the isSelected method to see which button was selected
instead of getting and checking the source.)
You need to set the fontSize variable (use 16 for small,
24 for medium, and 32 for large) in the if statement, then call the
setFont method to set the font for the saying object.
- In StyleGUI() instantiate a SizeListener and add it
to each button. Also add each button to the panel.
- Compile and run the program. Note that as the font size changes
the checkboxes and buttons re-arrange themselves in the panel. To
fix this, you could put each of the major components into separate
panels (you don't have to right now). There are also other ways to address
this problem that we will address later in the course.
Polymorphism
Consider the game of Monopoly.
The game consists of a sequential set of 40 squares containing
28 properties, 6 Action squares (3 "Chance", 3 "Community Chest"), 2 Tax
squares, "GO", "Jail", "Free Parking", and "Go To Jail.". The game is played
by moving through the set of squares. Every time a player lands of a
square, they take a different action, depending on the type of a square. For
example, if you land on a "Tax Square", you must pay the bank a certain amount
of money, but if you land on an "Action Square" you must draw a card from the
appropriate pile and follow the instructions on the card.
Note that
this is a perfect example of polymorphism. Take a deep breath and
relax, you are not implementing Monopoly during this lab. However you are
going to use polymorphism to describe the gameplay. To accomplish this
you should:
Print your work to turn in.
HAND IN:
- Printouts of your programs - make sure that your name is included in the
header comments (not just written on)
- Tar the files in your lab3 directory with the command
tar czf lab3.tgz .
and e-mail them to me (hughes@roanoke.edu)