This assignment has two main parts:
- You will create Java 2D graphical renderings
of BridgeState and WaterJugState objects to replace
the string representations provided by their toString
methods
- You will modify your problem solving framework from the previous
assignment so that the GUI presents a state's graphical rendering
Click
Program Behavior to the left for an example of one
approach to this assignment. Note:
- It is not necessary (nor desired) that you copy the example.
You are encouraged to be more creative than the current author.
- For full credit at least one of the two domains must
incorporate animation in its graphical rendering.
Before you start, use NetBeans to copy your
CS_2511_GUI
project from the previous assignment to a new NetBeans project
called
CS_2511_Framework_Graphics (right click the project node in
the
Projects window and select
Copy...).
You will add to the framework and application domains (bridge and water
jug problems) as described in this section.
Suggestion:
- Ignore the issues brought up by the animation
requirement until after you have successfully implemented and tested
the system for graphical presentation without animation
- Then revisit the animation issue by following the hints given later
The framework needs another abstract class
Canvas to represent
the object on which to paint graphical renderings of states.
This section suggests the way to do this.
After the previous assignment, your top-level framework structure
should look like that shown in the class diagram below.
A natural way to incorporate
Canvas is to associate it with
GUI:
- Should extend JComponent
- Should be declared to be abstract
- No abstract methods, but
- Must be subclassed to override the paintComponent method
- Constructor should take the first State object displayed
by the canvas and store it
- Should provide accessor and mutator for the state being
displayed
- It may help to also provide an accessor and mutator
for the previous state to carry out animation
- This class can also have any methods that might be generally
useful to subclasses
- Constructor should take a Canvas object as its second
argument and store it
(along with the Problem argument from before)
- The canvas, being a JComponent, should be added to the
GUI layout instead of the JTextArea from before
- In the move button listeners, if doMove is successful:
- The canvas must be told about the new state
- The canvas must be repainted
- Similar actions must be taken upon problem reset
Your
bridge and
waterjug packages need classes that
extend
Canvas.
Suppose they are
BridgeCanvas and
WaterJugCanvas,
respectively.
For both
BridgeCanvas and
WaterJugCanvas:
- Constructor should accept the appropriate initial state and
pass if off to the Canvas constructor using super
- Constructor should create and store any drawing objects that
are needed by paintComponent
- paintComponent should draw the objects required
to depict the problem's current state
- When using the setColor method
(from java.awt.Graphics), you can
create arbitrary colors using the Color constructor
(from java.awt)
taking three integers representing red, green, and blue values
- Here is a useful resource for finding suitable red, green, and
blue values:
RGB Color Chart
- To accurately position text on your canvas, see the special
topic on page 163 of the text
- Use the GeneralPath class (from java.awt.geom) to
draw arbitrary shapes:
- Create a path using new GeneralPath()
- Determine a point (x0,y0) that
is the start of the drawing
- Move to the start using
path.moveTo(x0,y0)
- Determine the remaining points on your drawing
(x1,y1), . . .
(xn,yn).
- Draw a line to (x1,y1) using
path.lineTo(x1,y1)
- . . .
- Draw a line to (xn,yn) using
path.lineTo(xn,yn)
- Complete the drawing back to
(x0,y0)
using path.closePath()
- The above procedure draws a closed figure with straight edges.
To incorporate curves, replace calls to lineTo with calls
to quadTo
- A useful tutorial:
Working With Java 2D Graphics
You can test your graphics only, in isolation from your GUI.
Or, you can test your GUI with graphics included.
Add the following
main method to
your
BridgeCanvas class:
public static void main(String[] args) {
JFrame frame = new JFrame("BridgeCanvas Test");
frame.add(new BridgeCanvas(new BridgeState(Position.WEST,
Position.WEST,
Position.WEST,
Position.WEST,
Position.WEST,
0)));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
Now run the
BridgeCanvas.java file to observe the rendering of
the state.
Change the states given to the
BridgeCanvas constructor to
observe different states.
Follow the same procedure with your
WaterJugCanvas class.
GUIs are constructed by three classes that you have copied over from
your previous assignment:
- BridgeGui (in the bridge package)
- WaterJugGui (in the waterjug package)
- TestFrame (in the framework.test package)
Since you have added a second parameter of type
Canvas to
the
GUI constructor, you need to add the appropriate parameter
to each of the
new GUI(...) calls in these test files.
Once that's done, you can run these files and they should behave as
before but with the graphical rendering of states.
Use the
Timer class (in
javax.swing) to
successively draw an object in a new location and repaint the canvas
on which it is drawn.
See the
animation example on pp. 164—169 of the
text for details on how a timer is used
to produce animation.
The rest of this section treats issues specific to this assignment.
- The successive redrawing of the shape(s) cannot be done
from within the Canvas object's paintComponent method itself
- So management of the timer must be done by some other method,
call it for example render, that will have to be added to the
abstract Canvas class, and which will have to be overridden
by any class that wants to do animation
- The GUI's move button listeners will have to call render
rather than repaint
- Classes that don't perform animation can simply have
their render methods call repaint
To the right is a sequence diagram showing the suggested interaction of the
canvas, timer, and timer listener objects.
Suppose you are animating the filling of a water jug.
- By initDrawCriteria is meant the initializing of the height of
the rectangle representing a water jug.
- By updateDrawCriteria is meant the incremental change needed to
the height of the rectangle in order to carry out the animation.
- Due to the way a timer works, the firing of
the actionPerformed method and updateDrawCriteria actions
are executed in a loop.
- It is up to the timer listener to determine if the animation
is finished and to either stop the timer or repaint the canvas
accordingly.
When your program is working correctly you will submit your entire Netbeans
project, but first:
- To double-check that everything is in order, click Build on
the menu bar and select Clean and Build Main Project.
- Run the bridge.BridgeGUI and waterjug.WaterJugGUI classes
to make sure everything works.
- Run the framework.test.TestFrame class to be doubly sure.
Outside of NetBeans, zip your project folder as
your-login-PA4.zip.
Email the zip file to your TA.
- Correctness, appearance and creativity of static graphical
renderings: 20 points
- Successful incorporation of animation: 10 points