PieGraph.java |
package graphics.charts; import gui.ClosableJFrame; import javax.swing.*; import java.awt.*; /** * PieGraph implements the Paintable interface and uses the update * method to draw a pie graphics.graph on a Canvas. * Requires an instance of DoubleData in order * to be constructed.<BR> * Global variables: * <UL> * <LI> DoubleData: instance of DoubleData so the graphics.graph is drawn * with the proper data * <LI> CIRCLESIZE: 360 degrees in a circle * <LI> startAngle: the point at which to begin drawing the pie graphics.graph * <LI> radius: the radius of the pie graphics.graph * <LI> centerX: the X coordinate of the center of the pie graphics.graph * <LI> centerY: the Y coordinate of the center of the pie graphics.graph * </UL> * * @author Allison McHenry * @author Douglas Lyon, PhD * @since JDK 1.3 */ public class PieGraph extends JComponent implements Paintable { //GLOBAL VARIABLES private static final double CIRCLESIZE = 360.0; private double startAngle = 0; private int centerX = 10; private int centerY = 10; private String labels[] = { "Apples", "Oranges", "Bananas", "Papayas" }; private DoubleData dd; private int radius = 0; //CONSTRUCTORS /** * Default constructor, used to instantiate an instance of PieGraph by * the testing class * @param _dd instance of DoubleData used to draw the graphics.graph */ public PieGraph() { this(400, 400); } /** * Constructor used to set just the radius * * @param _radius The pie radius */ public PieGraph(int _radius) { this(_radius * 2, _radius * 2); } /** * Constructor used to set just the radius * * @param w the image width * @param h the image height */ public PieGraph(int w, int h) { setSize(w, h); setBackground(Color.white); dd = new DoubleData(w, h); } public Dimension getPreferredSize() { return new Dimension(dd.getWidth(), dd.getHeight()); } public Dimension getMinimumSize() { return new Dimension(dd.getWidth(), dd.getHeight()); } /** * Draws the legend on the top canvas. The labels are passed in * and the percentage of the pie that each slice takes up * is calculated. The label color is determined by mapping * the number of the label to the corresponding color value * in the ColorUtils map. TO FIX: if the number of labels passed * does not correspond to the number of data points, the * labels won't match up correctly. This should throw an * exception. * * @param s Array of strings which correspond to each slice * @return p Panel with the labels drawn on it * @see DoubleData.#calculatePercentage * @see java.awt.Panel * @see java.awt.Label */ private JPanel getLegendPanel() { JPanel p = new JPanel(); String percentages[] = calculatePercentage(); ColorUtils cu = new ColorUtils(labels.length); p.setBackground(Color.white); p.setLayout(new GridLayout(0, 2)); for (int i = 0; i < labels.length; i++) { JLabel text = new JLabel(labels[i]); JLabel pct = new JLabel(percentages[i]); text.setForeground(cu.getColor(i)); pct.setForeground(cu.getColor(i)); p.add(text); p.add(pct); } return p; } /** * Constructor used to set the data, labels and title only * * @param _x The data to graphics.graph * @param _labels The labels which correspond to the data elements * @param _title The title of the graphics.graph */ public PieGraph(DoubleData _dd) { dd = _dd; setSize(dd.getWidth(), dd.getHeight()); } //BEGIN SETTER METHODS /** * Sets the center of the pie graphics.graph X and Y coordinates. * * @param _x X coordinate of center of pie graphics.graph * @param _y Y coordinate of center of pie graphics.graph */ public void setLocation(int x, int y) { centerX = x; centerY = y; } public void setValues(double[] _x) { dd.setXVals(_x); } /** * Sets the point on the circle where the pie should begin to be drawn. * * @param _startAngle Pie graphics.graph start angle */ public void setStartAngle(double _startAngle) { startAngle = _startAngle; } /** * Sets the X coordinate of the center of the pie graphics.graph. * * @param _centerX X-coordinate of center of pie */ public void setCenterX(int _centerX) { centerX = _centerX; } /** * Sets the Y coordinate of the center of the pie graphics.graph. * * @param _centerY Y-coordinate of center of pie */ public void setCenterY(int _centerY) { centerY = _centerY; } /** * Sets pie graphics.graph labels. Each label should correspond to one data point in the X array. * * @param _labels Pie graphics.graph labels */ public void setLabels(String[] _labels) { labels = _labels; } public void setRadius(int _radius) { radius = _radius; } /** * Gets the pie graphics.graph radius. * * @return radius Pie graphics.graph radius */ public int getRadius() { if (radius == 0) { return (Math.max(getSize().width, getSize().height)) / 2; } else { return radius; } } /** * Gets the point on the circle where the pie should begin to be drawn. * * @return _startAngle Pie graphics.graph start angle */ public double getStartAngle() { return startAngle; } /** * Gets the X coordinate of the center of the pie graphics.graph. * * @return centerX X-coordinate of center of pie */ public int getCenterX() { return centerX; } /** * Gets the Y coordinate of the center of the pie graphics.graph. * * @return centerY Y-coordinate of center of pie */ public int getCenterY() { return centerY; } /** * Gets pie graphics.graph labels. Each label should correspond to one data point in the X array. * * @return _labels Pie graphics.graph labels */ public String[] getLabels() { return labels; } //UTILITY METHODS /** * Calls the update method to paint this data from DoubleData onto * an image. It calls update instead of overriding the paint method * directly because "paint" is a specialized method name and it * conflicts with the "paint" method in the PieGraphCanvas class. * * @param g Graphics context for drawing * @see PieGraphPanel.#update */ public void paint(Graphics g) { drawGraph(g); } /** * Draws the circle for the pie graphics.graph. The data to graphics.graph * is determined by the values in the X array. The values in * the Y array are irrelevant.StartAngle is a global variable * from DoubleData which defaults to zero (top of the pie). * * @param g Graphics context for drawing * @see PieGraph.#paint * @see DoubleData.#getSumX * @see ColorUtils.#getColor * @see java.awt.Graphics.#fillArc */ private void drawGraph(Graphics g) { double startAngle = getStartAngle(); ColorUtils cu = new ColorUtils(dd.getXVals().length); double angleSize = ((CIRCLESIZE / (getSumX()))); double items[] = dd.getXVals(); for (int i = 0; i < items.length; i++) { //360.0 * items[i] / d.getSum(); double centralAngle = (angleSize * items[i]); g.setColor(cu.getColor(i)); g.fillArc(getCenterX(), getCenterY(), getRadius(), getRadius(), (int) (startAngle - 5), (int) (centralAngle + 5)); startAngle = startAngle + centralAngle; } } /** * Calculates the percentage of the pie occupied by each slice. * Returns the value as a string so it can be written as a label on the * pieGraph Panel. * * * @return pctStrings The percentage of the pie occupied by each slice * @see #getSumX * @see CreatePiePanel.#getLegendPanel */ protected String[] calculatePercentage() { double sum = getSumX(); double[] x = dd.getXVals(); double[] percentages = new double[x.length]; for (int i = 0; i < x.length; i++) { percentages[i] = (x[i] / sum) * 100; } String[] pctStrings = new String[percentages.length]; for (int j = 0; j < pctStrings.length; j++) { pctStrings[j] = new String(Double.toString(percentages[j]) + "%"); System.out.println("String=" + pctStrings[j]); } return pctStrings; } /** * Computes the sum of all the data values. Used to calculate the percentage per slice * of each data point in a pie graphics.graph. * * @param _x The array of data to add * @return sum Sum of data x * @see #getSumX */ private double computeSum(double x[]) { double sum = 0; for (int i = 0; i < x.length; i++) sum = x[i] + sum; return sum; } /** * Default no-argument method to calculate the sum of the array xVals, which is a global * variable * * @return sum Sum of data xVals * @see #calculatePercentage */ private double getSumX() { double sum = computeSum(dd.getXVals()); return sum; } public static void main(String args[]) { ClosableJFrame cf = new ClosableJFrame(); Container c = cf.getContentPane(); DoubleData dd = new DoubleData(200, 200); double[] xes = new double[]{30, 30, 30, 60}; for (int i = 0; i < dd.getXVals().length; i++) { double[] yes = dd.getXVals(); System.out.println("value=" + yes[i]); } PieGraph pg = new PieGraph(200, 200); String[] labels = new String[]{"Tiger", "Lion", "Alligator", "Mongoose"}; pg.setLabels(labels); pg.setValues(xes); c.add(pg); c.add(pg.getLegendPanel()); c.setLayout(new FlowLayout()); c.setBackground(Color.white); cf.setSize(300, 300); cf.setVisible(true); } }