如何用数组数据填充直方图?

时间:2019-01-23 01:42:06

标签: java swing graphics

我无法正确填充直方图。

我得到了一个大的数据文件,里面充满了代表GPA的双打,其中大约有5500个。我创建了一种方法来计算数据的计数,均值和标准偏差,但是我的最后一个问题是对数据进行图形处理。

我要为每个可能的等级(其中12个等级)制作一个直方图,并用图形绘制每个等级的总和。

我认为我已经正确编码了每个年级的总和,但是在实际绘制直方图时,我无法弄清楚fillRect所需的4个参数。

我一直在研究不同的变量,但是似乎没有什么能让我接近。

感谢您的帮助。

private static int[] gradeCounts(double[] stats) throws Exception{

   double stdv = 0;
   double sum = 0;
   double sum2 = 0;
   double variance = 0;

  Scanner fsc = new Scanner(new File("introProgGrades.txt"));

  while (!fsc.hasNextDouble())
     fsc.nextLine();

  int[] binCounts = new int[NUM_OF_GRADE_CATEGORIES];

  double x = 0;

  while (fsc.hasNextDouble()){
        stats[2]++;
     x = fsc.nextDouble();
     sum += x;
     sum2 += x * x;

     if (x == 0.0) 
      binCounts[0]++;
     else if (x == 0.6666667)
        binCounts[1]++;
     else if (x == 1.0)
         binCounts[2]++;
     else if (x == 1.3333333)
         binCounts[3]++;
     else if (x == 1.6666667)
         binCounts[4]++;
     else if (x == 2.0)
         binCounts[5]++;
     else if (x == 2.3333333)
         binCounts[6]++;
     else if (x == 2.6666667)
         binCounts[7]++;
     else if (x == 3.0)
         binCounts[8]++;
     else if (x == 3.3333333)
         binCounts[9]++;
     else if (x == 3.6666667)
         binCounts[10]++;
     else 
        binCounts[11]++;


     }

  stats[0] = sum/stats[2];
  variance = (stats[2] * sum2 - sum * sum) / (stats[2]*(stats[2]-1));
  stdv = Math.sqrt(variance);
  stats[1] = stdv;

 return binCounts;

}

我遇到的麻烦:

  private static void plotHistogram(int[] binCounts){
  int max = Arrays.stream(binCounts).max().getAsInt();

  DrawingPanel panel = new DrawingPanel (800,800);
  Graphics2D g = panel.getGraphics();
   g.fillRect(0, 0, 800/binCounts.length,max);

}

我认为我必须使用for循环来遍历数据,但这是我毫无头绪的fillRect参数。

1 个答案:

答案 0 :(得分:0)

  

但是在实际绘制直方图时,我无法找出fillRect所需的4个参数。

JavaDocs在属性及其含义上非常明确,它只是一个具有位置(x / y)和大小(宽度/高度)的盒子

  

public abstract void fillRect((int x,                                 诠释                                 整数宽度                                 int高度)

  填充指定的矩形。矩形的左右边缘分别位于x和x +   宽度-1。顶部和底部边缘位于y和y +高度-1。   产生的矩形覆盖一个区域宽度像素宽度高度像素   高。使用图形上下文的当前填充矩形   颜色。

参数:
x-要填充的矩形的x坐标。
  y-要填充的矩形的y坐标。
width-宽度   
height-要填充的矩形的高度   充满。

     

我一直在研究不同的变量,但是似乎没有什么能让我接近。

因此,我想到了两件事,第一件事来自上面的JavaDocs ...

  

使用图形上下文的当前填充矩形   颜色

这是容易忘记的事情

第二个是您似乎误解了绘画在Swing中的工作方式。

Swing中的绘画有一个非常具体且有据可查的工作流程。您应该做的第一件事是阅读Performing Custom PaintingPainting in AWT and Swing,以更好地了解绘画的工作方式以及应该如何使用它。

除了能够返回JComponent#getGraphics之外,没有充分的理由调用null,这只是最后一次绘制循环的快照,在下一次绘制过程中将被清除干净(可能出于多种原因随时发生)。

相反,您将需要一个自定义组件并替代其paintComponent方法。

然后,您应该通读2D Graphics线索,以更好地了解API的工作方式以及可以提供的功能/功能。

例如。...

Example

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.util.Arrays;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                Random rnd = new Random();
                int[] binCounts = new int[10];
                for (int index = 0; index < binCounts.length; index++) {
                    binCounts[index] = rnd.nextInt(100);
                }
                JFrame frame = new JFrame();
                frame.add(new DrawingPanel(binCounts));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class DrawingPanel extends JPanel {

        private int[] binCounts;
        private int max;

        public DrawingPanel(int[] binCounts) {
            this.binCounts = binCounts;
            max = Arrays.stream(binCounts).max().getAsInt();

            System.out.println(max);
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            int barWidth = 800 / binCounts.length;
            for (int i = 0; i < binCounts.length; i++) {
                int barHeight = (int)((binCounts[i] / (double)max) * getHeight());
                // I personally would cache this until the state of the component
                // changes, but for brevity
                Rectangle rect = new Rectangle(i * barWidth, getHeight() - barHeight, barWidth, barHeight);
                g2d.setColor(Color.BLUE);
                g2d.fill(rect);
                g2d.setColor(Color.BLACK);
                g2d.draw(rect);
            }
            g2d.dispose();

        }
    }

}