View Single Post
  #13 (permalink)  
Old 11-03-2007, 12:08 AM
hardwired hardwired is offline
Senior Member
 
Join Date: Jul 2007
Posts: 1,222
hardwired is on a distinguished road
Code:
import java.awt.*; import java.awt.font.*; import java.awt.geom.*; import javax.swing.*; public class LineChart extends JPanel { double[] data = { 230, 1340, 6500, 330 }; int[] years = { 1995, 1996, 1997, 1998 }; final int PAD = 20; final int VPAD = 45; final int HPAD = 55; final int TICK = 2; final int STICK = 3; protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D)g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); drawAxes(g2); // plot data Point2D.Double lastP = null; for(int j = 0; j < data.length; j++) { g2.setPaint(Color.red); Point2D.Double p = modelToView(j, data[j]); g2.fill(new Ellipse2D.Double(p.x-2, p.y-2, 4, 4)); if(lastP != null) { g2.setPaint(Color.blue); g2.draw(new Line2D.Double(lastP, p)); } lastP = p; } } private Point2D.Double modelToView(double x, double y) { double w = getWidth(); double h = getHeight(); double tx = HPAD; double ty = h-VPAD; AffineTransform at = AffineTransform.getTranslateInstance(tx, ty); double xScale = (w - HPAD-PAD)/(data.length-1); int max = (int)Math.ceil(getMaxValue()); double yScale = (h - PAD-VPAD)/max; at.scale(xScale, -yScale); Point2D.Double dst = new Point2D.Double(); at.transform(new Point2D.Double(x, y), dst); return dst; } private void drawAxes(Graphics2D g2) { double w = getWidth(); double h = getHeight(); double xInc = (w - HPAD-PAD)/(data.length-1); int max = (int)Math.ceil(getMaxValue()); double yInc = (h - PAD-VPAD)/max; // grid lines g2.setPaint(new Color(220,230,240)); // vertical for(int j = 0; j <= data.length; j++) { double x = HPAD + j*xInc; g2.draw(new Line2D.Double(x, VPAD, x, h-VPAD)); } // horizontal for(int j = 0; j <= max; j=j+max/data.length) { double y = PAD + j*yInc; g2.draw(new Line2D.Double(HPAD, y, w-HPAD, y)); } // axes g2.setPaint(new Color(51,51,51)); // ordinate g2.draw(new Line2D.Double(HPAD, PAD, HPAD, h-VPAD)); // tick marks for(int j = 0; j <= max; j=j+max/data.length) { double y = PAD + j*yInc; g2.draw(new Line2D.Double(HPAD, y, HPAD-TICK, y)); } // labels Font font = g2.getFont().deriveFont(14f); g2.setFont(font); FontRenderContext frc = g2.getFontRenderContext(); LineMetrics lm = font.getLineMetrics("0", frc); for(int j = 0; j <= max; j=j+max/data.length) { String s = String.valueOf(max-j); float y = (float)(PAD + j*yInc + lm.getDescent()); float width = (float)font.getStringBounds(s, frc).getWidth(); float x = (float)(HPAD - TICK - STICK - width); g2.drawString(s, x, y); } // title char[] chars = "big numbers".toCharArray(); // May look better without the descent. float height = lm.getAscent() /*+ lm.getDescent()*/; float y0 = PAD + (float)((h - PAD-VPAD - height*chars.length)/2); float y = y0 + lm.getAscent(); for(int j = 0; j < chars.length; j++) { g2.drawString(String.valueOf(chars[j]), STICK, y); y += /*lm.getDescent() +*/ lm.getAscent(); } // abcissa g2.draw(new Line2D.Double(HPAD, h-VPAD, w-PAD, h-VPAD)); // tick marks for(int j = 0; j <= data.length; j++) { double x = HPAD + j*xInc; g2.draw(new Line2D.Double(x, h-VPAD, x, h-VPAD+TICK)); } // labels for(int j = 0; j < data.length; j++) { String s = String.valueOf(years[j]); float width = (float)font.getStringBounds(s, frc).getWidth(); float x = (float)(HPAD + j*xInc - width/2); y = (float)(h-VPAD + TICK + STICK + lm.getAscent()); g2.drawString(s, x, y); } // title String s = "years"; float width = (float)font.getStringBounds(s, frc).getWidth(); float x = HPAD + (float)((w - HPAD-PAD - width)/2); y = (float)(h - STICK - lm.getDescent()); g2.drawString(s, x, y); } private double getMaxValue() { double max = -Double.MAX_VALUE; for(int j = 0; j < data.length; j++) { if(data[j] > max) max = data[j]; } return max; } public static void main(String[] args) { JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.getContentPane().add(new LineChart()); f.setSize(400,400); f.setLocation(200,200); f.setVisible(true); } }
Reply With Quote