Copyright © Cay S. Horstmann 2009
This work is licensed under a Creative Commons
Attribution-Noncommercial-Share Alike 3.0 United States License.
Put the answers to the questions in each step into the lab report. Copy/paste the programs that you write in the lab.
This icon indicates optional tasks. Do those if you have time.
Drawable
InterfaceWe start with the code for the car viewer from Chapter 3. Download and unzip it on your computer. (Remember to actually unzip the file. Some operating systems—which we won't name to protect the guilty—display a zip file as a folder, giving you the illusion that it is unzipped.)
You'll get a directory carviewer
containing a directory
src
, which contains several Java files. (Some operating
systems—which we won't name ...—will make a
carviewer
directory inside a carviewer
directory.
That's ok—just keep it in mind in the next step.)
Start NetBeans and select File → New Project from the menu. In the dialog, select Java and Java Project with Existing Sources.
Click Next. Give the project a name Lab12A. Click on
the Browse button and select the carviewer
directory. You want to select the directory containing the
src
subdirectory, not the src
subdirectory itself.
Click Next.
Click Add Folder next to the Source Package
Folders text area. Select the src
folder inside the
carviewer
folder.
Click Finish.
Look at the Projects window at the left side of the NetBeans window. The Lab12A project should be in boldface. If not, right-click and select Set as Main Project
Select Run → Run Main Project from the menu. What happens?
private ArrayList<Car>
cars
to the CarComponent
classpaintComponent
method with a loop that draws
all cars in the array list CarComponent
constructor, fill cars
with five cars with different locationsRun your program to check that it draws the cars. Attach the source code
of the CarComponent
class to your lab report.
House
class in the project. Modify the
CarComponent
class so that it also draws houses:
private ArrayList<House>
houses
paintComponent
method, add a loop that draws all
houses in the array list CarComponent
constructor, fill
houses
with five houses with different locationsRun your program to check that it draws the cars and houses. Attach the source code to your lab report.
CarComponent
class in the
Projects window. Select Refactor->Rename from the menu.
Rename the class to to SuburbanScene
.
Open the CarViewer
class. What do you notice?
This smart renaming doesn't happen in BlueJ. It is one of the reasons you want to switch to a real development environment.
public void draw(Graphics2D g2)
Make an interface Drawable
that declares a single method
draw
. Make Car
and House
implement
that interface.
Compile and run your program to make sure it still works.
Car
and House
(and potentially other classes)
implement a common interface. Change the SuburbanScene
as
follows:
drawables
that holds Drawable
objectspaintComponent
method so that it draws the
elements of drawables
. Car
and
House
objects to the drawables
array. Run your program to check that it draws the cars and houses. Attach the
source code of the SuburbanScene
class to your lab report.
paintComponent
method again. It should contain
code similar to
for (Drawable d : drawables) d.draw(g2);
How does the compiler know that d
(or whatever you called
it) has a draw
method?
drawables.add(new Car(30, 40));
But drawables
is not an
ArrayList<Car>
. It is an
ArrayList<Drawable>
. Why is it legal to add a
Car
?
Ball
that also implements the
Drawable
interface. Its draw
method should call
g2.setColor(Color.RED); g2.fill(new Ellipse2D.Double(x, y, DIAMETER, DIAMETER)); g2.setColor(Color.BLACK);
Add a few balls to the drawables
array list.
Attach a screen shot with cars, houses, and balls to your lab report.
Dog
class for an example. You also
need this image in the same directory. Add some dogs
to your scene.
Moveable
Interfacepublic interface Moveable { void move(); }
Have the Car
and Ball
classes (but
not the House
class) implement the
Moveable
interface in addition to the Drawable
interface. Simply add a comma and Moveable
to the class
declarations. Compile your code. What happens? Why?
move
method for Car
, simply execute
x = xLeft++
, and for Ball
, y--
.
Provide these methods and compile your code. It should now compile without errors.
d.draw(g2)
(or whatever you called
the Drawable
), add the lines
if (d instanceof Moveable) { d.move(); }
Compile. What happens? Why?
move
on a variable that isn't
of type Moveable
. Here, we need to use a cast.
Moveable m = (Moveable) d;
The cast is safe because we already checked that d instanceof
Moveable
. Using the cast, make the moveable objects move before they
are drawn. Compile to make sure you don't get any errors. What is your
paintComponent
method now?
Timer
like this:
import javax.swing.Timer; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; ... public class CarViewer { public static void main(String[] args) { final JFrame frame = new JFrame(); // Add final to the variable declaration ... frame.setVisible(true); class TimerListener implements ActionListener { public void actionPerformed(ActionEvent event) { frame.repaint(); } } ActionListener listener = new TimerListener(); Timer t = new Timer(100, listener); // 100 milliseconds between actions t.start(); } }
Run your program. What happens?
Attach the code for all classes to your lab report.
Measurable
InterfaceMeasurable
interface from the textbook is a bit
abstract. The following tasks should help with visualizing it.
Make the House
class implement the Measurable
interface. The
getMeasure
method should return the area of the house
(width * height
).
Compile the class to make sure there are no syntax errors. Attach the code to your lab report.
SuburbanScene
, add an instance variable
private Measurable largest;
In the constructor, add a local variable data
of type DataSet
. Add all houses to the data
set, then set largest
to data.getMaximum()
.
In the paintComponent
class, locate the call to
d.draw(g2)
(or whatever variable you used) and change it to
if (d == largest) g2.setColor(Color.GREEN); d.draw(g2); g2.setColor(Color.BLACK);
Now run your program. What happens? Why?
Unzip these source files somewhere.
In Netbeans, make a project Lab12D
containing these files.
Look at the ClocksComponent
class. In its
paintComponent
method, add a loop that draws all clocks in the
clocks
array list. Run the program. What happens?
Clock
class. Instead, we will use
inheritance.
Make a new class ColoredClock
that extends
Clock
. In the ClocksComponent
, change one of the
two clocks to ColoredClock
. Compile and run. (To make a new
class in Netbeans, go to in the Project tree at the left, expand the
project, then Source Packages, right-click on the "default package" icon,
then select New -> Java class.)
draw
method. Add a draw
method to the
ColoredClock
class. To get started, let's draw a yellow
background:
public void draw(Graphics2D g2) { Color c = Color.YELLOW; g2.setColor(c); g2.fill(getBounds()); g2.setColor(Color.BLACK); }
(The getBounds
method returns the rectangle bounding the
clock.)
Run your program. What happens?
super
.getHours
to get the current hours. If they are between 6
(inclusive) and 18 (exclusive), then draw a yellow background. Otherwise,
draw a blue background. Compile and run. What is your code?update
method updates
the current time. Let's override it so that it adds 12 to the hours:
public void update() { super.update(); hours = (hours + 12) % 24; }
Compile. What happens? Why?
Clock
class to fix this
method. Compile and run. What happens?
When you are done, remove that update method (or comment it out by
surrounding it with /*
and */
).
A WorldClock
differs from a Clock
in two ways:
Make a class WorldClock
that extends Clock
.
Add instance variables label
and offset
. Make a
constructor that sets them. Add a new WorldClock("New York",
-3)
and new WorldClock("London", -8)
to the
ClocksComponent
. Compile and run.
draw
method of WorldClock
that contains a call
Rectangle bounds = getBounds(); double x = bounds.getX(); double y = bounds.getY(); g2.drawString(label, (int) x, (int) y);
Compile and run. What happens? (If one of the labels doesn't show up, move the clock down a bit.)
draw
method so that it shows the time and
the label. update
method, protect
against taking the %
of a negative number. For example, if it
is currently 6:00 in San Francisco, the time in London is 21:00, but (6 -
9) % 24 would be -3. Fix this and test by calling the
toString
method.