Java/2D Graphics GUI/Chart

Материал из Java эксперт
Перейти к: навигация, поиск

Demo bar chart and pie chart

<source lang="java"> import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GridLayout; import java.awt.Image; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.Shape; import java.awt.Stroke; import java.awt.event.ruponentEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.awt.geom.AffineTransform; import java.awt.geom.Arc2D; import java.awt.geom.GeneralPath; import java.awt.geom.Rectangle2D; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; public class Charts2D extends JFrame {

 public Charts2D() {
   super("2D Charts");
   setSize(720, 280);
   getContentPane().setLayout(new GridLayout(1, 3, 10, 0));
   getContentPane().setBackground(Color.white);
   int[] xData = new int[8];
   int[] yData = new int[8];
   for (int i = 0; i < xData.length; i++) {
     xData[i] = i;
     yData[i] = (int) (Math.random() * 100);
     if (i > 0)
       yData[i] = (yData[i - 1] + yData[i]) / 2;
   }
   JChart2D chart = new JChart2D(JChart2D.LineChart, xData.length, xData, yData,
       "Line Chart");
   chart.setStroke(new BasicStroke(5f, BasicStroke.CAP_ROUND,
       BasicStroke.JOIN_MITER));
   chart.setLineColor(new Color(0, 28, 28));
   getContentPane().add(chart);
   chart = new JChart2D(JChart2D.ColumnChart, xData.length, xData, yData,
       "Column Chart");
   GradientPaint gp = new GradientPaint(0, 100, Color.white, 0, 300,
       Color.blue, true);
   chart.setGradient(gp);
   chart.setEffectIndex(JChart2D.Gradientffect);
   chart.setDrawShadow(true);
   getContentPane().add(chart);
   chart = new JChart2D(JChart2D.PieChart, xData.length, xData, yData,
       "Pie Chart");
   ImageIcon icon = new ImageIcon("largejexplogo.GIF");
   chart.setForegroundImage(icon.getImage());
   chart.setEffectIndex(JChart2D.ImageEffect);
   chart.setDrawShadow(true);
   getContentPane().add(chart);
   WindowListener wndCloser = new WindowAdapter() {
     public void windowClosing(WindowEvent e) {
       System.exit(0);
     }
   };
   addWindowListener(wndCloser);
   setVisible(true);
 }
 public static void main(String argv[]) {
   new Charts2D();
 }

} class JChart2D extends JPanel {

 public static final int LineChart = 0;
 public static final int ColumnChart = 1;
 public static final int PieChart = 2;
 public static final int PLainEffect = 0;
 public static final int Gradientffect = 1;
 public static final int ImageEffect = 2;
 protected int m_chartType = LineChart;
 protected JLabel titleLabel;
 protected ChartPanel chartPanel;
 protected int dataLength;
 protected int[] xData;
 protected int[] yData;
 protected int xMin;
 protected int xMax;
 protected int yMin;
 protected int yMax;
 protected double[] pieData;
 protected int m_effectIndex = PLainEffect;
 protected Stroke stroke;
 protected GradientPaint gradient;
 protected Image foregroundImage;
 protected Color lineColor = Color.black;
 protected Color columnColor = Color.blue;
 protected int columnWidth = 12;
 protected boolean drawShadow = false;
 public JChart2D(int type, int nData, int[] yData, String text) {
   this(type, nData, null, yData, text);
 }
 public JChart2D(int type, int nData, int[] xD, int[] yD, String text) {
   super(new BorderLayout());
   setBackground(Color.white);
   titleLabel = new JLabel(text, JLabel.CENTER);
   add(titleLabel, BorderLayout.NORTH);
   m_chartType = type;
   if (xData == null) {
     xData = new int[nData];
     for (int k = 0; k < nData; k++)
       xData[k] = k;
   }
   if (yD == null)
     throw new IllegalArgumentException("yData can"t be null");
   if (nData > yD.length)
     throw new IllegalArgumentException("Insufficient yData length");
   if (nData > xD.length)
     throw new IllegalArgumentException("Insufficient xData length");
   dataLength = nData;
   xData = xD;
   yData = yD;
   xMin = xMax = 0; // To include 0 into the interval
   yMin = yMax = 0;
   for (int k = 0; k < dataLength; k++) {
     xMin = Math.min(xMin, xData[k]);
     xMax = Math.max(xMax, xData[k]);
     yMin = Math.min(yMin, yData[k]);
     yMax = Math.max(yMax, yData[k]);
   }
   if (xMin == xMax)
     xMax++;
   if (yMin == yMax)
     yMax++;
   if (m_chartType == PieChart) {
     double sum = 0;
     for (int k = 0; k < dataLength; k++) {
       yData[k] = Math.max(yData[k], 0);
       sum += yData[k];
     }
     pieData = new double[dataLength];
     for (int k = 0; k < dataLength; k++)
       pieData[k] = yData[k] * 360.0 / sum;
   }
   chartPanel = new ChartPanel();
   add(chartPanel, BorderLayout.CENTER);
 }
 public void setEffectIndex(int effectIndex) {
   m_effectIndex = effectIndex;
   repaint();
 }
 public int getEffectIndex() {
   return m_effectIndex;
 }
 public void setStroke(Stroke s) {
   stroke = s;
   chartPanel.repaint();
 }
 public void setForegroundImage(Image img) {
   foregroundImage = img;
   repaint();
 }
 public Image getForegroundImage() {
   return foregroundImage;
 }
 public Stroke getStroke() {
   return stroke;
 }
 public void setGradient(GradientPaint g) {
   gradient = g;
   repaint();
 }
 public GradientPaint getGradient() {
   return gradient;
 }
 public void setColumnWidth(int c) {
   columnWidth = c;
   chartPanel.calcDimensions();
   chartPanel.repaint();
 }
 public int setColumnWidth() {
   return columnWidth;
 }
 public void setColumnColor(Color c) {
   columnColor = c;
   chartPanel.repaint();
 }
 public Color getColumnColor() {
   return columnColor;
 }
 public void setLineColor(Color c) {
   lineColor = c;
   chartPanel.repaint();
 }
 public Color getLineColor() {
   return lineColor;
 }
 public void setDrawShadow(boolean d) {
   drawShadow = d;
   chartPanel.repaint();
 }
 public boolean getDrawShadow() {
   return drawShadow;
 }
 class ChartPanel extends JComponent {
   int xMargin = 5;
   int yMargin = 5;
   int pieGap = 10;
   int m_x;
   int m_y;
   int m_w;
   int m_h;
   ChartPanel() {
     enableEvents(ComponentEvent.ruPONENT_RESIZED);
   }
   protected void processComponentEvent(ComponentEvent e) {
     calcDimensions();
   }
   public void calcDimensions() {
     Dimension d = getSize();
     m_x = xMargin;
     m_y = yMargin;
     m_w = d.width - 2 * xMargin;
     m_h = d.height - 2 * yMargin;
     if (m_chartType == ColumnChart) {
       m_x += columnWidth / 2;
       m_w -= columnWidth;
     }
   }
   public int xChartToScreen(int x) {
     return m_x + (x - xMin) * m_w / (xMax - xMin);
   }
   public int yChartToScreen(int y) {
     return m_y + (yMax - y) * m_h / (yMax - yMin);
   }
   public void paintComponent(Graphics g) {
     int x0 = 0;
     int y0 = 0;
     if (m_chartType != PieChart) {
       g.setColor(Color.black);
       x0 = xChartToScreen(0);
       g.drawLine(x0, m_y, x0, m_y + m_h);
       y0 = yChartToScreen(0);
       g.drawLine(m_x, y0, m_x + m_w, y0);
     }
     Graphics2D g2 = (Graphics2D) g;
     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
         RenderingHints.VALUE_ANTIALIAS_ON);
     g2.setRenderingHint(RenderingHints.KEY_RENDERING,
         RenderingHints.VALUE_RENDER_QUALITY);
     if (stroke != null)
       g2.setStroke(stroke);
     GeneralPath path = new GeneralPath();
     switch (m_chartType) {
     case LineChart:
       g2.setColor(lineColor);
       path.moveTo(xChartToScreen(xData[0]),
           yChartToScreen(yData[0]));
       for (int k = 1; k < dataLength; k++)
         path.lineTo(xChartToScreen(xData[k]),
             yChartToScreen(yData[k]));
       g2.draw(path);
       break;
     case ColumnChart:
       for (int k = 0; k < dataLength; k++) {
         xMax++;
         int x = xChartToScreen(xData[k]);
         int w = columnWidth;
         int y1 = yChartToScreen(yData[k]);
         int y = Math.min(y0, y1);
         int h = Math.abs(y1 - y0);
         Shape rc = new Rectangle2D.Double(x, y, w, h);
         path.append(rc, false);
         xMax--;
       }
       if (drawShadow) {
         AffineTransform s0 = new AffineTransform(1.0, 0.0, 0.0,
             -1.0, x0, y0);
         s0.concatenate(AffineTransform.getScaleInstance(1.0, 0.5));
         s0.concatenate(AffineTransform.getShearInstance(0.5, 0.0));
         s0.concatenate(new AffineTransform(1.0, 0.0, 0.0, -1.0,
             -x0, y0));
         g2.setColor(Color.gray);
         Shape shadow = s0.createTransformedShape(path);
         g2.fill(shadow);
       }
       if (m_effectIndex == Gradientffect && gradient != null) {
         g2.setPaint(gradient);
         g2.fill(path);
       } else if (m_effectIndex == ImageEffect
           && foregroundImage != null)
         fillByImage(g2, path, 0);
       else {
         g2.setColor(columnColor);
         g2.fill(path);
       }
       g2.setColor(lineColor);
       g2.draw(path);
       break;
     case PieChart:
       double start = 0.0;
       double finish = 0.0;
       int ww = m_w - 2 * pieGap;
       int hh = m_h - 2 * pieGap;
       if (drawShadow) {
         ww -= pieGap;
         hh -= pieGap;
       }
       for (int i = 0; i < dataLength; i++) {
         finish = start + pieData[i];
         double f1 = Math.min(90 - start, 90 - finish);
         double f2 = Math.max(90 - start, 90 - finish);
         Shape shp = new Arc2D.Double(m_x, m_y, ww, hh, f1, f2 - f1,
             Arc2D.PIE);
         double f = (f1 + f2) / 2 * Math.PI / 180;
         AffineTransform s1 = AffineTransform.getTranslateInstance(
             pieGap * Math.cos(f), -pieGap * Math.sin(f));
         s1.translate(pieGap, pieGap);
         Shape piece = s1.createTransformedShape(shp);
         path.append(piece, false);
         start = finish;
       }
       if (drawShadow) {
         AffineTransform s0 = AffineTransform.getTranslateInstance(
             pieGap, pieGap);
         g2.setColor(Color.gray);
         Shape shadow = s0.createTransformedShape(path);
         g2.fill(shadow);
       }
       if (m_effectIndex == Gradientffect && gradient != null) {
         g2.setPaint(gradient);
         g2.fill(path);
       } else if (m_effectIndex == ImageEffect
           && foregroundImage != null)
         fillByImage(g2, path, 0);
       else {
         g2.setColor(columnColor);
         g2.fill(path);
       }
       g2.setColor(lineColor);
       g2.draw(path);
       break;
     }
   }
   protected void fillByImage(Graphics2D g2, Shape shape, int xOffset) {
     if (foregroundImage == null)
       return;
     int wImg = foregroundImage.getWidth(this);
     int hImg = foregroundImage.getHeight(this);
     if (wImg <= 0 || hImg <= 0)
       return;
     g2.setClip(shape);
     Rectangle bounds = shape.getBounds();
     for (int i = bounds.x + xOffset; i < bounds.x + bounds.width; i += wImg)
       for (int j = bounds.y; j < bounds.y + bounds.height; j += hImg)
         g2.drawImage(foregroundImage, i, j, this);
   }
 }

}


 </source>   



Drawing a Pie Chart

<source lang="java"> import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import javax.swing.JComponent; import javax.swing.JFrame; class Slice {

 double value;
 Color color;
 public Slice(double value, Color color) {
   this.value = value;
   this.color = color;
 }

} class MyComponent extends JComponent {

 Slice[] slices = { new Slice(5, Color.black), new Slice(33, Color.green),
     new Slice(20, Color.yellow), new Slice(15, Color.red) };
 MyComponent() {
 }
 public void paint(Graphics g) {
   drawPie((Graphics2D) g, getBounds(), slices);
 }
 void drawPie(Graphics2D g, Rectangle area, Slice[] slices) {
   double total = 0.0D;
   for (int i = 0; i < slices.length; i++) {
     total += slices[i].value;
   }
   double curValue = 0.0D;
   int startAngle = 0;
   for (int i = 0; i < slices.length; i++) {
     startAngle = (int) (curValue * 360 / total);
     int arcAngle = (int) (slices[i].value * 360 / total);
     g.setColor(slices[i].color);
     g.fillArc(area.x, area.y, area.width, area.height, startAngle, arcAngle);
     curValue += slices[i].value;
   }
 }

} public class PieChart {

 public static void main(String[] argv) {
   JFrame frame = new JFrame();
   frame.getContentPane().add(new MyComponent());
   frame.setSize(300, 200);
   frame.setVisible(true);
 }

}


 </source>   



Simple bar chart

<source lang="java"> import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import javax.swing.JFrame; import javax.swing.JPanel; public class ChartPanel extends JPanel {

 private double[] values;
 private String[] names;
 private String title;
 public ChartPanel(double[] v, String[] n, String t) {
   names = n;
   values = v;
   title = t;
 }
 public void paintComponent(Graphics g) {
   super.paintComponent(g);
   if (values == null || values.length == 0)
     return;
   double minValue = 0;
   double maxValue = 0;
   for (int i = 0; i < values.length; i++) {
     if (minValue > values[i])
       minValue = values[i];
     if (maxValue < values[i])
       maxValue = values[i];
   }
   Dimension d = getSize();
   int clientWidth = d.width;
   int clientHeight = d.height;
   int barWidth = clientWidth / values.length;
   Font titleFont = new Font("SansSerif", Font.BOLD, 20);
   FontMetrics titleFontMetrics = g.getFontMetrics(titleFont);
   Font labelFont = new Font("SansSerif", Font.PLAIN, 10);
   FontMetrics labelFontMetrics = g.getFontMetrics(labelFont);
   int titleWidth = titleFontMetrics.stringWidth(title);
   int y = titleFontMetrics.getAscent();
   int x = (clientWidth - titleWidth) / 2;
   g.setFont(titleFont);
   g.drawString(title, x, y);
   int top = titleFontMetrics.getHeight();
   int bottom = labelFontMetrics.getHeight();
   if (maxValue == minValue)
     return;
   double scale = (clientHeight - top - bottom) / (maxValue - minValue);
   y = clientHeight - labelFontMetrics.getDescent();
   g.setFont(labelFont);
   for (int i = 0; i < values.length; i++) {
     int valueX = i * barWidth + 1;
     int valueY = top;
     int height = (int) (values[i] * scale);
     if (values[i] >= 0)
       valueY += (int) ((maxValue - values[i]) * scale);
     else {
       valueY += (int) (maxValue * scale);
       height = -height;
     }
     g.setColor(Color.red);
     g.fillRect(valueX, valueY, barWidth - 2, height);
     g.setColor(Color.black);
     g.drawRect(valueX, valueY, barWidth - 2, height);
     int labelWidth = labelFontMetrics.stringWidth(names[i]);
     x = i * barWidth + (barWidth - labelWidth) / 2;
     g.drawString(names[i], x, y);
   }
 }
 public static void main(String[] argv) {
   JFrame f = new JFrame();
   f.setSize(400, 300);
   double[] values = new double[3];
   String[] names = new String[3];
   values[0] = 1;
   names[0] = "Item 1";
   values[1] = 2;
   names[1] = "Item 2";
   values[2] = 4;
   names[2] = "Item 3";
   f.getContentPane().add(new ChartPanel(values, names, "title"));
   WindowListener wndCloser = new WindowAdapter() {
     public void windowClosing(WindowEvent e) {
       System.exit(0);
     }
   };
   f.addWindowListener(wndCloser);
   f.setVisible(true);
 }

}


 </source>