在JavaJFreeChart中强制指定数量和一组域轴标签

0yg35tkg  于 2021-06-27  发布在  Java
关注(0)|答案(1)|浏览(367)

我正在尝试编写一个方法,在jfreechart中创建一个简单的正态分布图,并将其保存为一个文件。下面是一个输出图像的例子,它几乎就是我想要的

请注意,x轴上正好有9个记号。中间的一个是分布的平均值,其余的刻度表示标准差。平均值的每个标准偏差都有一个记号。
下面是另一个图表的例子,它显示了一个正态分布,平均值为7,标准偏差为5,没有其他代码变化。

这不是我想要的。突然只有8个记号,中间没有记号来表示平均数。似乎jfreechart只想使用漂亮的整数,而不是奇数7作为中心记号。
我试过阅读其他关于强制使用axis标签的stackoverflow问题,但似乎其他人都想使用某种形式的日期。如果我可以简单地指定9个精确的值来放置在轴上,而不是自动生成它们,这会有所帮助,但我不知道如何做到这一点。
还有一个问题。如果你看图表边附近的曲线,它会被剪切到绘图框的下方,并进入刻度线。我想在曲线和记号之间添加填充。我试着用 plot.getRangeAxis().setRange(-0.01, 0.09); 但我遇到了一个奇怪的问题,正态分布的高度似乎受到其宽度的影响。大的平均值和标准差导致了这种情况的严重破坏(从统计学的Angular 来看,这是没有意义的,我开始质疑这种正态分布方法。)
不管怎样,我基本上需要一种方法来强制图表(a)在曲线周围添加填充,(b)精确地使用九个刻度线对应于平均值和四个标准差。
以下是我目前的代码,大部分是在网上被窃取的,并被删减到了看起来确实必要的地方:

static double mean = 7.0, sd = 5.0;
static Color line = new Color(0x6AA2A3);
static Color grey = new Color(0x555555);

public static void main(String[] args) throws IOException {
  // Create the normal distribution
  double minX = mean - (4 * sd), maxX = mean + (4 * sd);
  Function2D normal = new NormalDistributionFunction2D(mean, sd);
  XYDataset dataset = DatasetUtils.sampleFunction2D(normal, minX, maxX, 100, "Normal");

  JFreeChart chart = ChartFactory.createXYLineChart(null, null, null, dataset, PlotOrientation.VERTICAL, false, false, false);
  chart.setBorderVisible(true);

  // Create and format the Plot
  XYPlot plot = chart.getXYPlot();
  plot.setBackgroundPaint(Color.WHITE);
  plot.getRangeAxis().setVisible(false);
  plot.setOutlineVisible(false);

  // Format the X axis to look pretty
  NumberAxis domain = (NumberAxis) plot.getDomainAxis();
  domain.setRange(minX, maxX);
  domain.setAxisLineVisible(false);
  domain.setAutoRangeStickyZero(false);
  domain.setTickUnit(new NumberTickUnit(sd));
  domain.setTickLabelFont(new Font("Roboto", Font.PLAIN, 20));
  domain.setTickLabelPaint(grey);
  domain.setTickMarkStroke(new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
  domain.setTickMarkInsideLength(8);
  domain.setTickMarkPaint(grey);

  // Create a renderer to turn the chart into an image
  XYLineAndShapeRenderer render = (XYLineAndShapeRenderer) plot.getRenderer(0);
  render.setSeriesStroke(0, new BasicStroke(4));
  render.setSeriesPaint(0, line);

  // Output the final image
  chart.setPadding(new RectangleInsets(5, 20, 20, 20));
  BufferedImage image = chart.createBufferedImage(600,400);

  File outFile = new File("graph.png");
  outFile.createNewFile();
  ImageIO.write(image, "png", outFile);
}
i5desfxk

i5desfxk1#

对于请求a), plot.setAxisOffset(new RectangleInsets(5,5,5,5)); 应该会成功的。对于请求b),一般建议是 refreshTicks(Graphics2D g2, AxisState state,Rectangle2D dataArea,RectangleEdge edge)ValueAxis 类并返回一个合适的记号列表。尽管这样做可能看起来有点吓人,但如果你的逻辑很简单的话就不是了。您可以尝试简单地为自动生成的勾选列表中的平均值添加一个numbertick。

相关问题