0

I've been going through a 2D/Swing tutorial and have made a chart that runs a loop 20 times, and adds 20 different points to the chart. My issue is that only one point ever appears, and its always on the x-axis.

The loop is running 20 times from seeing my console log messages. The loop itself is at the bottom of the code.

I'm still quite new to Java so any suggestions or pointers would be great.

package scattergraph;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
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.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

/**
 *
 * @author scott
 */
public class ScatterGraph extends JPanel {

    private List<Double> scores;
    private int padding = 20;
    private int labelPadding = 12;
    private int numberYDivisions = 6;
    private int pointWidth = 10;
    private Color gridColor = new Color(200, 200, 200, 200);
    private Color pointColor = new Color(255, 0, 255);
    private Color lineColor = new Color(255, 255, 253);
    private static final Stroke GRAPH_STROKE = new BasicStroke(2f);

    public ScatterGraph(List<Double> 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() - (3 * padding) - labelPadding) / (scores.size() - 1);
        double yScale = ((double) getHeight() - (2 * padding) - labelPadding) / (getMaxScore() - getMinScore());


    List<Point> graphPoints = new ArrayList<>();
    for(int i = 0; i < scores.size(); i++){

        int x1 = (int)(i * xScale + padding + labelPadding);
        int y1 = (int)((getMaxScore() - scores.get(i) * yScale) + padding);

        graphPoints.add(new Point(x1, y1));
    }

    g2.setColor(Color.WHITE);
    g2.fillRect(padding + labelPadding, padding, getWidth() - (2*padding) - labelPadding, getHeight() - 2 * padding - labelPadding);
    g2.setColor(Color.BLUE);

    for(int i = 0; i < numberYDivisions + 1; i++){
        int x0 = padding + labelPadding;
        int x1 = pointWidth + padding + labelPadding;
        int y0 = getHeight() - ((i * (getHeight() - padding * 2 - labelPadding)) / numberYDivisions + padding + labelPadding);

        int y1 = y0;
        if(scores.size() > 0){
            g2.setColor(gridColor);
            g2.drawLine(padding + labelPadding + 1 + pointWidth, y0, getWidth() - padding, y1);
            g2.setColor(Color.BLACK);
            String yLabel = ((int) ((getMinScore() + (getMaxScore() - getMinScore()) * ((i * 8.0) / numberYDivisions)) * 100))/ 100.0 + "";

            FontMetrics metrics = g2.getFontMetrics();
            int labelWidth = metrics.stringWidth(yLabel);
            g2.drawString(yLabel, x0 - labelWidth - 6, y0 + (metrics.getHeight() / 2) - 3);

        }
            g2.drawLine(x0, y0, x1, y1);

    }

    for (int i = 0; i < scores.size(); i++){

        if (scores.size() > 1) {

            int x0 = i * (getWidth() - padding * 2 - labelPadding) / (scores.size() - 1) + padding + labelPadding;
            int x1 = x0;
            int y0 = getHeight() - padding - labelPadding;
            int y1 = y0 - pointWidth;
            if ((i % ((int) ((scores.size() / 8.0)) + 3)) == 0) {

                g2.setColor(gridColor);
                g2.drawLine(x0, getHeight() - padding - labelPadding - 1 - pointWidth, x1, padding);
                g2.setColor((Color.BLACK));
                String xLabel = i + "";
                FontMetrics metrics = g2.getFontMetrics();
                int labelWidth = metrics.stringWidth(xLabel);
                g2.drawString(xLabel, x0 - labelWidth / 2, y0 + metrics.getHeight() + 3);

            }

            g2.drawLine(x0, y0, x1, y1);



        }

    }

    g2.drawLine(padding + labelPadding, getHeight() - padding - labelPadding, padding + labelPadding, padding);
    g2.drawLine(padding + labelPadding, getHeight() - padding - labelPadding, getWidth() - padding, getHeight() - padding - labelPadding);

    Stroke oldStroke = g2.getStroke();
    g2.setColor(lineColor);
    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(pointColor);
    for (int i = 0; i < graphPoints.size(); i++){

           int x = graphPoints.get(i).x - pointWidth / 2;
           int y = graphPoints.get(i).y - pointWidth / 2;
           int ovalW = pointWidth;
           int ovalH = pointWidth;
           g2.fillOval(x, y, ovalW, ovalH);

    }


    }
    private double getMinScore(){
        double minScore = Double.MAX_VALUE;
        for(Double score: scores){
            minScore = Math.min(minScore, score);
        }
        return minScore;
    }


    private double getMaxScore(){
            double maxScore = Double.MIN_VALUE;
        for(Double score: scores){
            maxScore = Math.min(maxScore, score);
        }
        return maxScore;
    }


    public void setScores(List<Double> scores) {

          this.scores = scores;
          invalidate();
          this.repaint();

    }

        public List<Double> getScores() {
        return scores;
    }

    private static void createAndShowGui(){

        List<Double> scores = new ArrayList();
        Random random = new Random();

        int maxDataPoints = 20;
        int maxScore = 8;

        for(int i = 0 ; i < maxDataPoints; i++){

            scores.add((double)random.nextDouble() * maxScore);
            System.out.println("Score added");
        }


        ScatterGraph mainPanel = new ScatterGraph(scores);
        mainPanel.setPreferredSize(new Dimension(700,600));

        JFrame frame = new JFrame("My Scatter Graph");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }


    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable(){

            public void run(){
                createAndShowGui();
            }    

        });
    }

}

1 Answer 1

1

I found two points.

  1. minus values of y.

You have some strange values of y.

You have to change follow statement in which the multiplication operates first

int y1 = (int) ((getMaxScore() - scores.get(i) * yScale) + padding);

to

int y1 = (int) (((getMaxScore() - scores.get(i)) * yScale) + padding);
  1. max score

The getMaxScore method must be changed

maxScore = Math.min(maxScore, score);

to

maxScore = Math.max(maxScore, score);

Here is a output image, if I understood this situation correctly.

out image

I hope this can help you.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks Tommy, that helped! Currently I'm arranging the program from code alone, and not view a GUI. I was following through this tutorial - docs.oracle.com/javase/tutorial/uiswing/learn/… which shows how you can drag/drop elements from the NetBeans IDE, and shows them live in a design window. How would I incorporate that into this project so that I can do things like drag and drog labels for both axis, and add a button to load in a file with data?
I've never been working with netbeans. I think It should be another question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.