使用 JFreeChart 为两个系列设置不同的 y 轴
Setting different y-axis for two series with JFreeChart
我正在使用 JFreeChart 使用折线图绘制两个数据系列 (XYSeries)。
复杂的因素是其中一个数据系列的 y 值通常比我的第二个数据系列的 y 值高得多(假设第一个系列的 y 值在数百万的数量级,而第二个系列的 y 值在数百个数量级)。我的第一个数据集中存在高值导致绘图范围如此之大,以至于我的第二个数据集的 y 值不再可理解。
在图中添加第二个 y 轴,这样我的两个数据系列都使用它们自己的 y 轴,可以解决这个问题。有谁知道如何使用 JFreeChart 做到这一点?
当前的完整性代码:
XYSeriesCollection dataset = new XYSeriesCollection();
XYSeries series1 = new XYSeries("series1");
XYSeries series2 = new XYSeries("series2");
// Here is my code to fill series1 and series2 with data
dataset.addSeries(series1);
dataset.addSeries(series2);
JFreeChart chart = ChartFactory.createXYLineChart(
"title", "x-axis title", "y-axis title", dataset, PlotOrientation.VERTICAL, true, true, false
);
chart.getXYPlot().setRenderer(new XYSplineRenderer());
您可以手动创建 JFreeChart 对象,而不是使用 ChartFactory。首先生成数据集和 Plot,将每个数据集设置为一个索引。然后您可以使用必要的 Axis 和 Renderer 自定义 Plot。这是一个使用具有两个数据集的虚拟数据的示例,每个数据集具有不同的 y 值:
//create the series - add some dummy data
XYSeries series1 = new XYSeries("series1");
XYSeries series2 = new XYSeries("series2");
series1.add(1000, 1000);
series1.add(1150, 1150);
series1.add(1250, 1250);
series2.add(1000, 111250);
series2.add(1150, 211250);
series2.add(1250, 311250);
//create the datasets
XYSeriesCollection dataset1 = new XYSeriesCollection();
XYSeriesCollection dataset2 = new XYSeriesCollection();
dataset1.addSeries(series1);
dataset2.addSeries(series2);
//construct the plot
XYPlot plot = new XYPlot();
plot.setDataset(0, dataset1);
plot.setDataset(1, dataset2);
//customize the plot with renderers and axis
plot.setRenderer(0, new XYSplineRenderer());//use default fill paint for first series
XYSplineRenderer splinerenderer = new XYSplineRenderer();
splinerenderer.setSeriesFillPaint(0, Color.BLUE);
plot.setRenderer(1, splinerenderer);
plot.setRangeAxis(0, new NumberAxis("Series 1"));
plot.setRangeAxis(1, new NumberAxis("Series 2"));
plot.setDomainAxis(new NumberAxis("X Axis"));
//Map the data to the appropriate axis
plot.mapDatasetToRangeAxis(0, 0);
plot.mapDatasetToRangeAxis(1, 1);
//generate the chart
JFreeChart chart = new JFreeChart("MyPlot", getFont(), plot, true);
chart.setBackgroundPaint(Color.WHITE);
JPanel chartPanel = new ChartPanel(chart);
我已经调整了上面的解决方案以使用最新版本的 JFreeChart (2019-Jan-29)。
如果正确导入了 JFreeChart 库,这将 运行 正确。我有一个 pom.xml
像这样设置导入
<dependency>
<groupId>org.jfree</groupId>
<artifactId>jfreechart</artifactId>
<version>1.0.19</version>
</dependency>
这是完整的代码片段:
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYSplineRenderer;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import javax.swing.*;
import java.awt.*;
class GraphTest2 {
// driver that actually runs the thing
public static void main(String[] args) {
SwingUtilities.invokeLater( () -> {
LineChartEx ex = new LineChartEx();
ex.setVisible(true);
});
}
}
class LineChartEx extends JFrame {
public LineChartEx() {
initUI();
}
private void initUI() {
//create the series - add some dummy data
XYSeries series1 = new XYSeries("series1");
XYSeries series2 = new XYSeries("series2");
series1.add(1000, 1000);
series1.add(1150, 1150);
series1.add(1250, 1250);
series2.add(1000, 111250);
series2.add(1150, 211250);
series2.add(1250, 311250);
//create the datasets
XYSeriesCollection dataset1 = new XYSeriesCollection();
XYSeriesCollection dataset2 = new XYSeriesCollection();
dataset1.addSeries(series1);
dataset2.addSeries(series2);
//construct the plot
XYPlot plot = new XYPlot();
plot.setDataset(0, dataset1);
plot.setDataset(1, dataset2);
//customize the plot with renderers and axis
plot.setRenderer(0, new XYSplineRenderer());//use default fill paint for first series
XYSplineRenderer splinerenderer = new XYSplineRenderer();
splinerenderer.setSeriesFillPaint(0, Color.BLUE);
plot.setRenderer(1, splinerenderer);
plot.setRangeAxis(0, new NumberAxis("Series 1"));
plot.setRangeAxis(1, new NumberAxis("Series 2"));
plot.setDomainAxis(new NumberAxis("X Axis"));
//Map the data to the appropriate axis
plot.mapDatasetToRangeAxis(0, 0);
plot.mapDatasetToRangeAxis(1, 1);
//generate the chart
JFreeChart chart = new JFreeChart("MyPlot", getFont(), plot, true);
chart.setBackgroundPaint(Color.WHITE);
//JPanel jpanel = new ChartPanel(chart);
// NEW PART THAT MAKES IT WORK
ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
chartPanel.setBackground(Color.white);
add(chartPanel);
pack();
setTitle("Line chart");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
我正在使用 JFreeChart 使用折线图绘制两个数据系列 (XYSeries)。 复杂的因素是其中一个数据系列的 y 值通常比我的第二个数据系列的 y 值高得多(假设第一个系列的 y 值在数百万的数量级,而第二个系列的 y 值在数百个数量级)。我的第一个数据集中存在高值导致绘图范围如此之大,以至于我的第二个数据集的 y 值不再可理解。
在图中添加第二个 y 轴,这样我的两个数据系列都使用它们自己的 y 轴,可以解决这个问题。有谁知道如何使用 JFreeChart 做到这一点?
当前的完整性代码:
XYSeriesCollection dataset = new XYSeriesCollection();
XYSeries series1 = new XYSeries("series1");
XYSeries series2 = new XYSeries("series2");
// Here is my code to fill series1 and series2 with data
dataset.addSeries(series1);
dataset.addSeries(series2);
JFreeChart chart = ChartFactory.createXYLineChart(
"title", "x-axis title", "y-axis title", dataset, PlotOrientation.VERTICAL, true, true, false
);
chart.getXYPlot().setRenderer(new XYSplineRenderer());
您可以手动创建 JFreeChart 对象,而不是使用 ChartFactory。首先生成数据集和 Plot,将每个数据集设置为一个索引。然后您可以使用必要的 Axis 和 Renderer 自定义 Plot。这是一个使用具有两个数据集的虚拟数据的示例,每个数据集具有不同的 y 值:
//create the series - add some dummy data
XYSeries series1 = new XYSeries("series1");
XYSeries series2 = new XYSeries("series2");
series1.add(1000, 1000);
series1.add(1150, 1150);
series1.add(1250, 1250);
series2.add(1000, 111250);
series2.add(1150, 211250);
series2.add(1250, 311250);
//create the datasets
XYSeriesCollection dataset1 = new XYSeriesCollection();
XYSeriesCollection dataset2 = new XYSeriesCollection();
dataset1.addSeries(series1);
dataset2.addSeries(series2);
//construct the plot
XYPlot plot = new XYPlot();
plot.setDataset(0, dataset1);
plot.setDataset(1, dataset2);
//customize the plot with renderers and axis
plot.setRenderer(0, new XYSplineRenderer());//use default fill paint for first series
XYSplineRenderer splinerenderer = new XYSplineRenderer();
splinerenderer.setSeriesFillPaint(0, Color.BLUE);
plot.setRenderer(1, splinerenderer);
plot.setRangeAxis(0, new NumberAxis("Series 1"));
plot.setRangeAxis(1, new NumberAxis("Series 2"));
plot.setDomainAxis(new NumberAxis("X Axis"));
//Map the data to the appropriate axis
plot.mapDatasetToRangeAxis(0, 0);
plot.mapDatasetToRangeAxis(1, 1);
//generate the chart
JFreeChart chart = new JFreeChart("MyPlot", getFont(), plot, true);
chart.setBackgroundPaint(Color.WHITE);
JPanel chartPanel = new ChartPanel(chart);
我已经调整了上面的解决方案以使用最新版本的 JFreeChart (2019-Jan-29)。
如果正确导入了 JFreeChart 库,这将 运行 正确。我有一个 pom.xml
像这样设置导入
<dependency>
<groupId>org.jfree</groupId>
<artifactId>jfreechart</artifactId>
<version>1.0.19</version>
</dependency>
这是完整的代码片段:
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYSplineRenderer;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import javax.swing.*;
import java.awt.*;
class GraphTest2 {
// driver that actually runs the thing
public static void main(String[] args) {
SwingUtilities.invokeLater( () -> {
LineChartEx ex = new LineChartEx();
ex.setVisible(true);
});
}
}
class LineChartEx extends JFrame {
public LineChartEx() {
initUI();
}
private void initUI() {
//create the series - add some dummy data
XYSeries series1 = new XYSeries("series1");
XYSeries series2 = new XYSeries("series2");
series1.add(1000, 1000);
series1.add(1150, 1150);
series1.add(1250, 1250);
series2.add(1000, 111250);
series2.add(1150, 211250);
series2.add(1250, 311250);
//create the datasets
XYSeriesCollection dataset1 = new XYSeriesCollection();
XYSeriesCollection dataset2 = new XYSeriesCollection();
dataset1.addSeries(series1);
dataset2.addSeries(series2);
//construct the plot
XYPlot plot = new XYPlot();
plot.setDataset(0, dataset1);
plot.setDataset(1, dataset2);
//customize the plot with renderers and axis
plot.setRenderer(0, new XYSplineRenderer());//use default fill paint for first series
XYSplineRenderer splinerenderer = new XYSplineRenderer();
splinerenderer.setSeriesFillPaint(0, Color.BLUE);
plot.setRenderer(1, splinerenderer);
plot.setRangeAxis(0, new NumberAxis("Series 1"));
plot.setRangeAxis(1, new NumberAxis("Series 2"));
plot.setDomainAxis(new NumberAxis("X Axis"));
//Map the data to the appropriate axis
plot.mapDatasetToRangeAxis(0, 0);
plot.mapDatasetToRangeAxis(1, 1);
//generate the chart
JFreeChart chart = new JFreeChart("MyPlot", getFont(), plot, true);
chart.setBackgroundPaint(Color.WHITE);
//JPanel jpanel = new ChartPanel(chart);
// NEW PART THAT MAKES IT WORK
ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
chartPanel.setBackground(Color.white);
add(chartPanel);
pack();
setTitle("Line chart");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}