Program: Grapher

Grapher is a simple program to read a table of numbers and graph them. The input format is two or more lines that each contain an X and a Y value. The output is an on-screen display that can also be printed. Figure 12-7 shows the results of running it with the following simple data; the first column is the X coordinate and the second is the Y coordinate of each point. The program scales the data to fit the window.

1.5  5
1.7  6
1.8  8
2.2  7
Grapher in action

Figure 12-7. Grapher in action

Example 12-8 shows the code.

Example 12-8. Grapher.java

import com.darwinsys.util.Debug;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.*;

/** Simple Graphing program.
 */
public class Grapher extends JPanel {
    /** Multiplier for range to allow room for a border */
    public final static float BORDERFACTOR = 1.1f;

    /* Small inner class to hold x, y. Called Apoint to differentiate
     * from java.awt.Point.
     */
    class Apoint {
        float x;
        float y;
        public String toString(  ) {
            return "Apoint("+x+","+y+")";
        }
    }

    /** The list of Apoint points. */
    protected Vector data;

    /** The minimum and maximum X values */
    protected float minx = Integer.MAX_VALUE, maxx = Integer.MIN_VALUE;
    /** The minimum and maximum Y values */
    protected float miny = Integer.MAX_VALUE, maxy = Integer.MIN_VALUE;
    /** The number of data points */
    protected int n;
    /** The range of X and Y values */
    protected float xrange, yrange;


    public Grapher(  ) {
        data = new Vector(  );
    }

    /** Read the data file named. Each line has an x and a y coordinate. */
    public void read(String fname) {
        LineNumberReader is = null;
        try {
            is = new LineNumberReader(new FileReader(fname));

            String txt;
            // Read the file a line at a time, parse it, save the data.
            while ((txt = is.readLine(  )) != null) {
                StringTokenizer st = new StringTokenizer(txt);
                try {
                    Apoint d = new Apoint(  );
                    d.x = Float.parseFloat(st.nextToken(  ));
                    d.y = Float.parseFloat(st.nextToken(  ));
                    data.add(d);
                } catch(NumberFormatException nfe) {
                    System.err.println("Invalid number on line " +
                        is.getLineNumber(  ));
                } // XXX catch out of range exception
            }
        } catch (FileNotFoundException e) {
            System.err.println("File " + fname + " unreadable: " + e);
        } catch (IOException e) {
            System.err.println("I/O error on line " + is.getLineNumber(  ));
        }
        n = data.size(  );
        if (n < 2) {
            System.err.println("Not enough data points!");
            return;
        }

        // find min & max
        for (int i=0 ; i < n; i++) {
            Apoint d = (Apoint)data.elementAt(i);
            if (d.x < minx) minx = d.x;
            if (d.x > maxx) maxx = d.x;
            if (d.y < miny) miny = d.y;
            if (d.y > maxy) maxy = d.y;
        }

        // Compute ranges
        xrange = (maxx - minx) * BORDERFACTOR;
        yrange = (maxy - miny) * BORDERFACTOR;
        Debug.println("range", "minx,x,r = " + minx +' '+ maxx +' '+ xrange);
        Debug.println("range", "miny,y,r = " + miny +' '+ maxy +' '+ yrange);
    }

    /** Called when the window needs painting.
     * Computes X and Y range, scales.
     */
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Dimension s = getSize(  );
        if (n < 2) {
            g.drawString("Insufficient data", 10, 40);
            return;
        }

        // Compute scale factors
        float xfact =  s.width  / xrange;
        float yfact =  s.height / yrange;

        // Scale and plot the data
        for (int i=0 ; i < n; i++) {
            Apoint d = (Apoint)data.elementAt(i);
            float x = (d.x-minx) * xfact;
            float y = (d.y-miny) * yfact;
            Debug.println("point", "AT " + i + " " + d + "; " +
                "x = " + x + "; y = " + y);
            // Draw a 5-pixel rectangle centered, so -2 both x and y.
            // AWT numbers Y from 0 down, so invert:
            g.drawRect(((int)x)-2, s.height-2-(int)y, 5, 5);
        }
    }

    public Dimension getPreferredSize(  ) {
        return new Dimension(150, 150);
    }

    public static void main(String[] rgs) {
        final JFrame f = new JFrame("Grapher");
        f.addWindowListener(new WindowAdapter(  ) {
            public void windowClosing(WindowEvent e) {
                f.setVisible(false);
                f.dispose(  );
                System.exit(0);
            }
        });
        Grapher g = new Grapher(  );
        f.setContentPane(g);
        f.setLocation(100, 100);
        f.pack(  );
        if (rgs.length == 0)
            g.read("Grapher.dat");
        else
            g.read(rgs[0]);
        f.setVisible(true);
    }
}

Most of the complexity of Grapher lies in determining the range and scaling. You could obviously extend this to draw fancier drawings such as bar charts and the like. If pie charts interest you, see ChartBean in the online source.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.147.77