2

This drawing a simple line graph in Java stack-overflow stuffs gives a good idea for drawing a line graph..but i'm not getting how to label the X and Y-axis within the graph. Can anyone please tell me how to label the x and y coordinates.

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.*;

@SuppressWarnings("serial")
public class DrawGraph extends JPanel {
   private static final int MAX_SCORE = 20;
   private static final int PREF_W = 800;
   private static final int PREF_H = 650;
   private static final int BORDER_GAP = 30;
   private static final Color GRAPH_COLOR = Color.green;
   private static final Color GRAPH_POINT_COLOR = new Color(150, 50, 50, 180);
   private static final Stroke GRAPH_STROKE = new BasicStroke(3f);
   private static final int GRAPH_POINT_WIDTH = 12;
   private static final int Y_HATCH_CNT = 10;
   private List<Integer> scores;

   public DrawGraph(List<Integer> scores) {
      this.scores = scores;
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D)g;
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

      double xScale = ((double) getWidth() - 2 * BORDER_GAP) / (scores.size() - 1);
      double yScale = ((double) getHeight() - 2 * BORDER_GAP) / (MAX_SCORE - 1);

      List<Point> graphPoints = new ArrayList<Point>();
      for (int i = 0; i < scores.size(); i++) {
         int x1 = (int) (i * xScale + BORDER_GAP);
         int y1 = (int) ((MAX_SCORE - scores.get(i)) * yScale + BORDER_GAP);
         graphPoints.add(new Point(x1, y1));
      }

      // create x and y axes 
      g2.drawLine(BORDER_GAP, getHeight() - BORDER_GAP, BORDER_GAP, BORDER_GAP);
      g2.drawLine(BORDER_GAP, getHeight() - BORDER_GAP, getWidth() - BORDER_GAP, getHeight() - BORDER_GAP);

      // create hatch marks for y axis. 
      for (int i = 0; i < Y_HATCH_CNT; i++) {
         int x0 = BORDER_GAP;
         int x1 = GRAPH_POINT_WIDTH + BORDER_GAP;
         int y0 = getHeight() - (((i + 1) * (getHeight() - BORDER_GAP * 2)) / Y_HATCH_CNT + BORDER_GAP);
         int y1 = y0;
         g2.drawLine(x0, y0, x1, y1);
      }

      // and for x axis
      for (int i = 0; i < scores.size() - 1; i++) {
         int x0 = (i + 1) * (getWidth() - BORDER_GAP * 2) / (scores.size() - 1) + BORDER_GAP;
         int x1 = x0;
         int y0 = getHeight() - BORDER_GAP;
         int y1 = y0 - GRAPH_POINT_WIDTH;
         g2.drawLine(x0, y0, x1, y1);
      }

      Stroke oldStroke = g2.getStroke();
      g2.setColor(GRAPH_COLOR);
      g2.setStroke(GRAPH_STROKE);
      for (int i = 0; i < graphPoints.size() - 1; i++) {
         int x1 = graphPoints.get(i).x;
         int y1 = graphPoints.get(i).y;
         int x2 = graphPoints.get(i + 1).x;
         int y2 = graphPoints.get(i + 1).y;
         g2.drawLine(x1, y1, x2, y2);         
      }

      g2.setStroke(oldStroke);      
      g2.setColor(GRAPH_POINT_COLOR);
      for (int i = 0; i < graphPoints.size(); i++) {
         int x = graphPoints.get(i).x - GRAPH_POINT_WIDTH / 2;
         int y = graphPoints.get(i).y - GRAPH_POINT_WIDTH / 2;;
         int ovalW = GRAPH_POINT_WIDTH;
         int ovalH = GRAPH_POINT_WIDTH;
         g2.fillOval(x, y, ovalW, ovalH);
      }
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   private static void createAndShowGui() {
      List<Integer> scores = new ArrayList<Integer>();
      Random random = new Random();
      int maxDataPoints = 16;
      int maxScore = 20;
      for (int i = 0; i < maxDataPoints ; i++) {
         scores.add(random.nextInt(maxScore));
      }
      DrawGraph mainPanel = new DrawGraph(scores);

      JFrame frame = new JFrame("DrawGraph");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
Community
  • 1
  • 1

1 Answers1

1

A lot will come down to "where" you want to render the text.

What I means is, do you want to modify the position of the existing lines, or do you want to render with the BORDER_GAP

You can start by having a look at Working with Text APIs

You could start with something simple, such as...

FontMetrics fm = g2.getFontMetrics();
// create hatch marks for y axis. 
for (int i = 0; i < Y_HATCH_CNT; i++) {
    int x0 = BORDER_GAP;
    int x1 = GRAPH_POINT_WIDTH + BORDER_GAP;
    int y0 = getHeight() - (((i + 1) * (getHeight() - BORDER_GAP * 2)) / Y_HATCH_CNT + BORDER_GAP);
    int y1 = y0;
    g2.drawLine(x0, y0, x1, y1);
    String value = Integer.toString(i);
    g2.drawString(value, x0 - fm.stringWidth(value), y0 + (fm.getAscent() / 2));
}

// and for x axis
for (int i = 0; i < scores.size() - 1; i++) {
    int x0 = (i + 1) * (getWidth() - BORDER_GAP * 2) / (scores.size() - 1) + BORDER_GAP;
    int x1 = x0;
    int y0 = getHeight() - BORDER_GAP;
    int y1 = y0 - GRAPH_POINT_WIDTH;
    g2.drawLine(x0, y0, x1, y1);
    String value = Integer.toString(i);
    g2.drawString(value, x0 - (fm.stringWidth(value) / 2), y0 + fm.getAscent());
}

Which will renderer a number (corresponding to the index of the loop) next to each hatch for example...

Updated with rotation example

Now if you wanted to rotate, say the x-series, so the labels ran vertically, you could do something like...

FontMetrics fm = g2.getFontMetrics();
// create hatch marks for y axis. 
for (int i = 0; i < Y_HATCH_CNT; i++) {
    int x0 = BORDER_GAP;
    int x1 = GRAPH_POINT_WIDTH + BORDER_GAP;
    int y0 = getHeight() - (((i + 1) * (getHeight() - BORDER_GAP * 2)) / Y_HATCH_CNT + BORDER_GAP);
    int y1 = y0;
    g2.drawLine(x0, y0, x1, y1);
    AffineTransform oldTransform = g2.getTransform();
    AffineTransform newTransform = new AffineTransform();
    newTransform.translate(-fm.getHeight() / 2, 0);
    newTransform.rotate(Math.toRadians(-90), x0, y0);
    g2.setTransform(newTransform);
    String value = Integer.toString(i);
    g2.drawString(value, x0 - (fm.stringWidth(value) / 2), y0 + (fm.getAscent() / 2));
    g2.setTransform(oldTransform);
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Sir Is there anything like this to draw histograms in java swing –  Mar 04 '13 at 06:49
  • You could take a look at [this](http://stackoverflow.com/questions/12518496/drawing-a-graphical-histogram/12520104#12520104), but I would recommend taking a look at [JFreeChart](http://www.jfree.org/jfreechart/) as well – MadProgrammer Mar 04 '13 at 06:53
  • Generally, it's more flexible. The same data series could be used across multiple types of charts. It has different rendering options and chart types, has mouse support and if I'm not wrong it can scale/zoom charts, its had thousands, if not millions of coder hours poured into and it's free – MadProgrammer Mar 04 '13 at 08:36