在 Java JFreeChart 中强制使用特定数量和一组域轴标签
Forcing a specific number and set of domain axis labels in Java JFreeChart
我正在尝试编写一种方法来在 JFreeChart 中创建正态分布的简单图形并将其保存为文件。这是一个输出图像的示例,它几乎正是我想要的
注意 x 轴上正好有 9 个刻度线。中间的一个是分布的平均值,其余的刻度表示标准差。与平均值的每个标准偏差有一个刻度。
这是另一个图表示例,显示了均值为 7、标准差为 5 的正态分布,并且没有其他代码更改。
这不是我想要的。突然只有8个刻度线,中间没有刻度线来标记均值。看来 JFreeChart 只想使用漂亮的整数而不是奇数 7 作为中心刻度。
我已经尝试阅读有关强制轴标签的其他 Whosebug 问题,但似乎其他人都想用某种形式的日期来做到这一点。如果我可以简单地指定 9 个准确的值放在轴上而不是自动生成它们,那将会有所帮助,但我不知道该怎么做。
还有另外一个问题。如果您查看图表两侧附近的曲线,它会剪裁到图框下方,并且 运行 进入刻度线。我想在曲线和刻度线之间添加填充。我尝试使用 plot.getRangeAxis().setRange(-0.01, 0.09);
之类的东西,但我 运行 遇到了一个奇怪的问题,正态分布的高度似乎受其宽度的影响。大的均值和标准差会导致它惨遭破坏。 (从统计学的角度来看,这毫无意义,我开始质疑这种正态分布方法。)
无论如何,我基本上需要一种方法来强制图表 (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);
}
请求 a),
plot.setAxisOffset(new RectangleInsets(5,5,5,5));
应该做的伎俩。
对于请求 b),一般建议是覆盖
refreshTicks(Graphics2D g2, AxisState state,Rectangle2D dataArea,RectangleEdge edge)
的
ValueAxis
class 和 return 合适的刻度列表。虽然这样做可能看起来有点吓人,但如果您的逻辑很简单,那就不是了。您可以尝试简单地为自动生成的刻度列表添加一个 NumberTick 作为均值。
我正在尝试编写一种方法来在 JFreeChart 中创建正态分布的简单图形并将其保存为文件。这是一个输出图像的示例,它几乎正是我想要的
注意 x 轴上正好有 9 个刻度线。中间的一个是分布的平均值,其余的刻度表示标准差。与平均值的每个标准偏差有一个刻度。
这是另一个图表示例,显示了均值为 7、标准差为 5 的正态分布,并且没有其他代码更改。
这不是我想要的。突然只有8个刻度线,中间没有刻度线来标记均值。看来 JFreeChart 只想使用漂亮的整数而不是奇数 7 作为中心刻度。
我已经尝试阅读有关强制轴标签的其他 Whosebug 问题,但似乎其他人都想用某种形式的日期来做到这一点。如果我可以简单地指定 9 个准确的值放在轴上而不是自动生成它们,那将会有所帮助,但我不知道该怎么做。
还有另外一个问题。如果您查看图表两侧附近的曲线,它会剪裁到图框下方,并且 运行 进入刻度线。我想在曲线和刻度线之间添加填充。我尝试使用 plot.getRangeAxis().setRange(-0.01, 0.09);
之类的东西,但我 运行 遇到了一个奇怪的问题,正态分布的高度似乎受其宽度的影响。大的均值和标准差会导致它惨遭破坏。 (从统计学的角度来看,这毫无意义,我开始质疑这种正态分布方法。)
无论如何,我基本上需要一种方法来强制图表 (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);
}
请求 a),
plot.setAxisOffset(new RectangleInsets(5,5,5,5));
应该做的伎俩。
对于请求 b),一般建议是覆盖
refreshTicks(Graphics2D g2, AxisState state,Rectangle2D dataArea,RectangleEdge edge)
的
ValueAxis
class 和 return 合适的刻度列表。虽然这样做可能看起来有点吓人,但如果您的逻辑很简单,那就不是了。您可以尝试简单地为自动生成的刻度列表添加一个 NumberTick 作为均值。