CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 2 of 2
  1. #1
    Join Date
    Mar 2011
    Posts
    11

    Drawing graphs in Java

    So recently I've been looking for some software to draw simple line graphs. I came across some code which does almost exactly what I want, thus I don't need to install other libraries. The only problem is that the code I came across doesn't post the values on the x-axis and the y-axis.

    This is the code:
    Code:
    import java.awt.*;
    import java.awt.font.*;
    import java.awt.geom.*;
    import javax.swing.*;
    
    public class GraphingData extends JPanel {
        int[] data = {1,2,3,4,5,6,7,8,10,1,2,3,4,5,6,7,5,4,3,4,5,65,6,324,23,423,64,56, 74,42,23,34};
        final int PAD = 20;
    
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D)g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                                RenderingHints.VALUE_ANTIALIAS_ON);
            int w = getWidth();
            int h = getHeight();
            // Draw ordinate.
            g2.draw(new Line2D.Double(PAD, PAD, PAD, h-PAD));
            // Draw abcissa.
            g2.draw(new Line2D.Double(PAD, h-PAD, w-PAD, h-PAD));
            // Draw labels.
            Font font = g2.getFont();
            FontRenderContext frc = g2.getFontRenderContext();
            LineMetrics lm = font.getLineMetrics("0", frc);
            float sh = lm.getAscent() + lm.getDescent();
            // Ordinate label.
            String s = "Strategy Counter";
            float sy = PAD + ((h - 2*PAD) - s.length()*sh)/2 + lm.getAscent();
            for(int i = 0; i < s.length(); i++) {
                String letter = String.valueOf(s.charAt(i));
                float sw = (float)font.getStringBounds(letter, frc).getWidth();
                float sx = (PAD - sw)/2;
                g2.drawString(letter, sx, sy);
                sy += sh;
            }
            // Abcissa label.
            s = "Rounds";
            sy = h - PAD + (PAD - sh)/2 + lm.getAscent();
            float sw = (float)font.getStringBounds(s, frc).getWidth();
            float sx = (w - sw)/2;
            g2.drawString(s, sx, sy);
            // Draw lines.
            double xInc = (double)(w - 2*PAD)/(data.length-1);
            double scale = (double)(h - 2*PAD)/getMax();
            g2.setPaint(Color.green.darker());
            for(int i = 0; i < data.length-1; i++) {
                double x1 = PAD + i*xInc;
                double y1 = h - PAD - scale*data[i];
                double x2 = PAD + (i+1)*xInc;
                double y2 = h - PAD - scale*data[i+1];
                g2.draw(new Line2D.Double(x1, y1, x2, y2));
            }
            // Mark data points.
    
        }
    
        private int getMax() {
            int max = -Integer.MAX_VALUE;
            for(int i = 0; i < data.length; i++) {
                if(data[i] > max)
                    max = data[i];
            }
            return max;
        }
    
        public static void main(String[] args) {
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.add(new GraphingData());
            f.setSize(800,400);
            f.setLocation(200,200);
            f.setVisible(true);
        }
    }
    This is the output:




    This is the desired output:

    Sorry about the cropping, it should be the same as the above picture.

    Has anyone any idea on how to make it output values for the axis?

  2. #2
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163

    Re: Drawing graphs in Java

    You need a loop for each axis.

    Calculate the maximum number of labels that will fit on the axis by dividing the length (or height) of the axis in pixels by the width (or height) of a label in pixels (including spacing to the next label).

    max X labels = axis length / (label width + spacer width)
    may Y labels = axis height / (label height + spacer height)

    Decide the value increment between labels by dividing the data value range by the max number of labels (if the value range is less than the max number of labels, the increment can be one).

    X value increment = X value range / max X labels
    Y value increment = Y value range / may Y labels

    For each axis, loop through the data range incrementing by the X or Y value increment calculated above.

    For the X axis, draw the X value as text at the X value ordinate and a Y ordinate below the X axis line.

    For the Y axis, draw the Y value as text at the Y value ordinate and an X ordinate left of the Y axis line.

    You may want to adjust the X or Y label ordinates to centre the labels around the X or Y value, and for the Y axis, to right-justify the labels.

    Alternatively, to make it look more professional, why not draw tics on the X and Y axes and arrange the labels every 5, or 10, or 20, etc., ticks ?

    However you want to do it, I strongly recommend drawing it out on paper first and working out how you want the axis labels or ticks to look, and how you'll calculate the label positions.

    But why not use a library like JChart or JGraphT that automatically gives you all that stuff?

    If I had eight hours to chop down a tree, I would spend 6 hours sharpening an axe...
    Anon.
    Last edited by dlorde; April 2nd, 2011 at 12:16 PM.
    Please use &#91;CODE]...your code here...&#91;/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured