前言
JFreeChart在CategoryPlot和XYPlot类中支持多轴和数据源显示。 我们利用这个特征可以在一个图表上显示两个或多个数据源数据,但对于数据包含的数据有巨大差距时留有一定的余地。
典型的,使用JFreeChart构建图表时,图表有一个单数据源、 单renderer、 单X/Y轴的图区最为常见。 然而,在一个图区上添加多个数据源、 多个renderer和多个轴也是可能的。 在本文实例中,展示了如何在一个图区上显示其他额外的数据源、 renderer和轴。
建议
当我们使用多轴图表时,我们需要为系列对应的轴提供一些可视化的建议。 比如在例子DualAxisDemo -Yves
中轴标签的颜色与系列颜色是相匹配的,这样是为了能够区分每个图的X轴与对应图表渲染结果之间的关系.
一.多轴图效果图
多轴图是支持同种类型的图
和不同种类型
的图的.(主要是共用x轴,通过添加Y轴的方式来实现的,多余不同类型的图表的多轴图,需要指定底部的图例显示,不然默认不显示图例),下面是两种不同的显示效果.
二.多轴图示例
建立多轴图表可以设置的项目
- 创建一个主图表
- 添加一个额外的轴
- 添加一个额外的数据源
- 添加一个额外的renderer
- 设置图例显示
1.创建一个图表
创建一个具有多轴、 多数据源、 多renderer的图表,我们首先要创建一个常规的图表(例如使用ChartFactory类创建)。 在本实例中,创建了一个时序图,代码如下:
XYDataset dataset1 = createDataset("Series 1", 100.0, new Minute(), 200);
JFreeChart chart = ChartFactory.createTimeSeriesChart(
"Multiple Axis Demo -Yves",
"Time of Day",
"Primary Range Axis",
dataset1,
true,
true,
false
);
2.添加额外的轴
如果在图区上添加额外的轴,我们使用setRangeAxis()方法来添加:
NumberAxis numberaxis = new NumberAxis("Range Axis 2");
xyplot.setRangeAxis(1, numberaxis);
xyplot.setRangeAxisLocation(1, AxisLocation.BOTTOM_OR_LEFT);
方法setRangeAxis()是用来添加图区的轴,注意轴的索引1已经被使用——我们添加其他轴时,通过增加该索引来添加新轴。(我们可以理解成主轴是从0开始,添加的额外的轴索引从1开始,一次递增1)
方法setRangeAxisLocation()允许我们指定轴出现的位置(使用AxisLocation类)。 我们添加的轴可以跟主坐标轴同一边,或者在对立边。
例如:如果指定的是AxisLocation.BOTTOM_OR_LEFT
,这意味着如果图区的方向是垂直的话,将在右边添加了一个Y轴,如果图区的方向是水平的话,将在底部添加一个Y轴。
值得注意的是:
- 如果我们没有使用setRangeAxis将额外的轴添加到plot上,即使设置了数据源原也是不会显示该图表的.
- 如果我们使用setRangeAxis将额外的轴添加到plot上,即使数据源没有数据,添加的坐标轴也是会显示的.
3.添加一个额外的数据源
在图区上添加一个额外的数据源,使用setDataset()方法:
XYDataset xydataset_0_ = createDataset("Series 2", 1000.0,
new Minute(), 170);
xyplot.setDataset(1, xydataset_0_);
缺省的,数据源将使用主轴来显示数据。 如果使数据源在另外的轴上显示数据,需使用方法mapDatasetToRangeAxis(int index, int axisIndex)
和mapDatasetToDomainAxis(int index, int axisIndex)
。 这两个方法接受两个参数,第一个参数是数据源的索引,第二个是轴的索引.
针对plot.setOrientation(PlotOrientation.VERTICAL);
垂直显示的图表,我们使用mapDatasetToRangeAxis(int index, int axisIndex)``,反之用
mapDatasetToDomainAxis(int index, int axisIndex)`
4.添加一个额外的renderer
当我们添加一个数据源时,通常为该数据源添加一个附加的renderer也是非常有意义的。 使用方法setRenderer():
StandardXYItemRenderer standardxyitemrenderer = new StandardXYItemRenderer();
xyplot.setRenderer(1, standardxyitemrenderer);
方法的第一个参数为xyplot.setDataset(1, xydataset_0_);
中添加的数据源的索引。 注意:如果我们不想为数据源指定一个附加的rendere,系统将默认使用主renderer,这样系列的颜色就会在主数据源和附加数据源之间共享。
附录
private static JFreeChart createChart() {
XYDataset dataset = createDataset("Series 1", 100.0D, new Minute(), 200);
JFreeChart chart = ChartFactory.createTimeSeriesChart("Multiple Axis Demo -Yves", "Time of Day", "Primary Range Axis", dataset, true, true, false);
chart.addSubtitle(new TextTitle("Four datasets and four range axes."));// 子标题
/** chart主题立即生效 **/
// 将当前主题应用于指定的图表。 提供此方法是为了方便,主题本身存储在ChartFactory类中。
// 可以理解流程主题中有对Renderer修饰的一系列属性,会覆盖之前以前的设置
ChartUtilities.applyCurrentTheme(chart);
XYPlot plot = (XYPlot) chart.getPlot();
plot.setOrientation(PlotOrientation.VERTICAL);
plot.setDomainPannable(true);// x轴自动增长
plot.setRangePannable(true);// y轴自动增长
plot.getRenderer().setSeriesPaint(0, Color.BLACK);// 设置主plot为黑色
// 主Plot是从0开始,其他的Plot从1开始
// 1
NumberAxis axis1 = new NumberAxis("Range Axis 2");
axis1.setAutoRangeIncludesZero(false);
plot.setRangeAxis(1, axis1);// 添加到Y轴上
plot.setRangeAxisLocation(1, AxisLocation.BOTTOM_OR_LEFT);// 设置坐标轴位置
XYDataset dataset2 = createDataset("Series 2", 1000.0D, new Minute(), 170);
plot.setDataset(1, dataset2);
plot.mapDatasetToRangeAxis(1, 1);
StandardXYItemRenderer renderer1 = new StandardXYItemRenderer();
plot.setRenderer(1, renderer1);
renderer1.setSeriesPaint(0, Color.red);
axis1.setLabelPaint(Color.red);
axis1.setTickLabelPaint(Color.red);
// 2
NumberAxis axis2 = new NumberAxis("Range Axis 3");
plot.setRangeAxis(2, axis2);
XYDataset dataset3 = createDataset("Series 3", 10000.0D, new Minute(), 170);
plot.setDataset(2, dataset3);
plot.mapDatasetToRangeAxis(2, 2);
StandardXYItemRenderer renderer2 = new StandardXYItemRenderer();
plot.setRenderer(2, renderer2);
renderer2.setSeriesPaint(0, Color.blue);
axis2.setLabelPaint(Color.blue);
axis2.setTickLabelPaint(Color.blue);
// 3
NumberAxis axis3 = new NumberAxis("Range Axis 4");
plot.setRangeAxis(3, axis3);
XYDataset dataset4 = createDataset("Series 4", 25.0D, new Minute(), 200);
plot.setDataset(3, dataset4);
plot.mapDatasetToRangeAxis(3, 3);
StandardXYItemRenderer renderer3 = new StandardXYItemRenderer();
plot.setRenderer(3, renderer3);
renderer3.setSeriesPaint(0, Color.green);
axis3.setLabelPaint(Color.green);
axis3.setTickLabelPaint(Color.green);
return chart;
}