EN 605.482 GUI Development with the Java Foundation Classes
Homework 2
In this homework, you will create
a simple line plot tool. This tool
will be general purpose enough to allow plotting of any data (as a single
line), and having the graph to be resizable by the user dragging the corners
of the window.
The requirements for this object
are as follows:
The graph will plot all data that falls within the graph extent. The graph does not need to resize to fit the data.
3. The
Java class that plots the data will plot any data that implements a "DrawWithAffine"
interface. The Java class that plots the data will not have plot data (minX, number tick marks) hardcoded into the class. The DrawWithAffine interface allows a
set of data to be drawn on the provided Graphics2D object, and to use the
provided AffineTransform to scale the data on the plot. The only method in
this interface is the following:
public void draw(Graphics2D g2d, AffineTransform
xfrm);
4.The object will add plots to be drawn with the following
method:
public
int addPlot(DrawWithAffine plot);
5. A LinePlot object, that implements
to the DrawWithAffine interface is provided. Use this object for your assignment.
6. In subsequent homeworks, you will be passing arguments and modifying the plot. Your object/constructor should support these options.
7. As the plot is resized, the following things should occur.
Axis Margins should remain fixed.Axis labels and graph title should recenterThe graph should have a minimum size.When the graph resizes, it should not cause any runtime errors, or infinite loopsThe graph (not the window) should have a limit as to how much it may be reduced.The graph title should have its text in a shadow
8. The plot shall be placed in a JInternalFrame in a JDesktopPane for viewing
Grading criteria is as follows:
| Item |
Points |
|---|---|
| Program Runs w/ no exceptions | 15 |
| Program does not hang on resizing | 20 |
| Graph Resizes | 20 |
| Titles/labels centered and rendered correctly | 20 |
| Correct constructor | 10 |
| Cover Page Complete | 5 |
| Neatness/Presentation | 5 |
| Extra Effort | 5 |
A sample output is shown in the applet below:
LinePlot defines the DrawWithAffine interface needed by the above object. It is a general data holding object. Feel free to use your own implementation of DrawWithAffine if you wish. an interface for an object to implement so that it may be used by the above object.
import java.awt.geom.*;
import java.awt.*;
/** Interface that allows you to draw something to a Graphics2D context,
* but applying the provided AffineTrasform to the data prior to drawing
it
* to the context.
*/
public interface DrawWithAffine {
/** Draw the data.
* @param g2d The graphics context to use
* @param xfrm The AffineTransform to adapt the object being drawn
*/
public void draw(Graphics2D g2d, AffineTransform xfrm);
}
package edu.jhu.en605482.part2;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
/** A set of data to be plotted in a Line. The color of the line can also
* be set. This object will draw the data using a provided Graphics2D
* object and an AffineTransform, which will scale the data to fit the
* graphic plot.
* @see edu.jhuapl.gui.PlotPad
*/
public class LinePlot implements DrawWithAffine {
/** Number of data points */
protected int numberOfPoints = 0;
/** The path that the data describes */
protected GeneralPath path;
/** The color of the data */
protected Color lineColor = Color.black;
/** Constructs a new LinePlot object with the specified winding rule
*and the specified initial capacity to store path coordinates. This
*number is an initial guess as to how many path segments are in the
*path, but the storage is expanded as needed to store whatever path
*segments are added to this path.
* @param initialCapacity the estimate for the number of path segments
* in the path
*/
public LinePlot(int initialCapacity) {
path = new GeneralPath(GeneralPath.WIND_EVEN_ODD, initialCapacity);
}
/** Constructs a new LinePlot object with the specified winding rule
*and the specified initial capacity to store path coordinates. This
*number is an initial guess as to how many path segments are in the
*path, but the storage is expanded as needed to store whatever path
*segments are added to this path.
* @param rule the winding rule
* @param initialCapacity the estimate for the number of path segments
* in the path
*/
public LinePlot(int windingRule, int initialCapacity) {
path = new GeneralPath(windingRule, initialCapacity);
}
/** Set the color of this line plot */
public void setColor(Color color) {
lineColor = color;
}
/** Constructs a new LinePlot object. If an operation performed on
*this path requires the interior of the path to be defined then the
*default NON_ZERO winding rule is used.*/
public LinePlot() {
path = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
}
/** Add a point to the plot. Note that plot values are currently
*stored as floats
* @param x the x point
* @param y the y point
*/
public void addPoint(double x, double y) {
addPoint((float)x, (float)y);
}
/** Add a point to the plot.
* @param x the x point
* @param y the y point
*/
public void addPoint(float x, float y) {
if (numberOfPoints == 0) {
path.moveTo(x, y);
} else {
path.lineTo(x, y);
}
numberOfPoints++;
}
/** Get the number of points in the plot.
* @return the number of points in the plot
*/
public int getNumberOfPoints() {
return numberOfPoints;
}
/** Clear out the points in this plot.*/
public void clear() {
path.reset();
numberOfPoints = 0;
}
/** Draw the data.
* @param g2d The graphics context to use
* @param scale The AffineTransform to adapt the data to the plot
*/
public void draw(Graphics2D g2d, AffineTransform scale) {
g2d.setPaint(lineColor);
g2d.draw(scale.createTransformedShape(path));
}
}
import javax.swing.*;
import java.awt.*;
public class HW2 {
/** Test program */
public static void main(String[] argv) {
final JFrame jf = new JFrame("Homework 2, HW2 test");
PlotPad pp = new PlotPad((new Dimension (400, 400)), // size
0, // minX
0, // minY
200.0, // maxX
1.0, // maxY
"Sin and Cos", // title
"X", // x label
"Y", // y label
20.0, // tick X
0.1, // tick Y
"##0", // format axis X
"##0.00"); // format axis Y
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setContentPane(pp);
jf.pack();
LinePlot lp = new LinePlot(100);
lp.setColor(Color.red);
pp.addPlot(lp);
LinePlot lp2 = new LinePlot(100);
lp2.setColor(Color.blue);
pp.addPlot(lp2);
for (int i=0; i < 100; i++) {
lp.addPoint(i*2.0, 0.5 + (Math.cos(i / 10.0)) / 2.0);
lp2.addPoint(i*2.0, 0.5 + (Math.sin(i / 10.0)) / 2.0);
}
jf.setVisible(true);
}
}
A Test file that generates a sin/cos data set is shown below