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
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.
18.191.147.77