Multiple Stacked Area datasets in JFreechart - jfreechart

I am using JFreechart and I'm trying to get what would be similar to the XYDifferenceRenderer but for a CategoryPlot. Issue I am running into is being able to plot multiple StackedAreaRenderers on the same plot. The following has one StackedArea that looks like it is floating. This is what I'm wanting.
package test;
import java.awt.Color;
import java.awt.Dimension;
import java.util.List;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.labels.StandardCategoryToolTipGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.AreaRendererEndType;
import org.jfree.chart.renderer.category.StackedAreaRenderer;
import org.jfree.chart.ui.ApplicationFrame;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.ui.RefineryUtilities;
/**
*
* #author buxk
*/
public class DifferenceWithCategories extends ApplicationFrame{
public DifferenceWithCategories(String title){
super(title);
final JFreeChart chart = createChart();
final ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new Dimension(500,270));
setContentPane(chartPanel);
}
/**
* Returns a sample dataset.
*
* #return The dataset.
*/
private CategoryDataset createDataset1() {
// row keys...
String series1 = "First";
// column keys...
String category1 = "Category 1";
String category2 = "Category 2";
String category3 = "Category 3";
String category4 = "Category 4";
String category5 = "Category 5";
// create the dataset...
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(4.0, series1, category1);
dataset.addValue(4.0, series1, category2);
dataset.addValue(3.0, series1, category3);
dataset.addValue(5.0, series1, category4);
dataset.addValue(5.0, series1, category5);
return dataset;
}
/**
* Returns a sample dataset.
*
* #return The dataset.
*/
private CategoryDataset createDataset2() {
// row keys...
String series2 = "Second";
// column keys...
String category1 = "Category 1";
String category2 = "Category 2";
String category3 = "Category 3";
String category4 = "Category 4";
String category5 = "Category 5";
// create the dataset...
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(5.0, series2, category1);
dataset.addValue(7.0, series2, category2);
dataset.addValue(6.0, series2, category3);
dataset.addValue(8.0, series2, category4);
dataset.addValue(6.0, series2, category5);
return dataset;
}
/**
* Returns a sample dataset.
*
* #return The dataset.
*/
private CategoryDataset createDataset3() {
// row keys...
String series3 = "Third";
// column keys...
String category1 = "Category 1";
String category2 = "Category 2";
String category3 = "Category 3";
String category4 = "Category 4";
String category5 = "Category 5";
// create the dataset...
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(1.0, series3, category1);
dataset.addValue(3.0, series3, category2);
dataset.addValue(2.0, series3, category3);
dataset.addValue(3.0, series3, category4);
dataset.addValue(4.0, series3, category5);
return dataset;
}
private CategoryDataset merge4StackedDataset(CategoryDataset d1, CategoryDataset d2){
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
List<Comparable> columnKeys = d1.getColumnKeys();
List<Comparable> d1RowKeys = d1.getRowKeys();
List<Comparable> d2RowKeys = d2.getRowKeys();
double minValue, maxValue;
for (Comparable columnKey : columnKeys) {
for (Comparable rowKey : d1RowKeys) {
for (Comparable d2RowKey : d2RowKeys) {
minValue = Math.min(d1.getValue(rowKey, columnKey).doubleValue(),d2.getValue(d2RowKey, columnKey).doubleValue());
maxValue = Math.max(d1.getValue(rowKey, columnKey).doubleValue(),d2.getValue(d2RowKey, columnKey).doubleValue());
dataset.addValue(minValue, rowKey, columnKey);
dataset.addValue(maxValue - minValue, d2RowKey, columnKey);
// dataset.addValue(d2.getValue(d2RowKey, columnKey).doubleValue(), d2RowKey, columnKey);
}
}
}
return dataset;
}
private JFreeChart createChart() {
CategoryDataset dataset1 = merge4StackedDataset(createDataset1(), createDataset2());
CategoryDataset dataset2 = merge4StackedDataset(createDataset1(), createDataset3());
//create chart with empty dataset
final JFreeChart chart = ChartFactory.createAreaChart(
"Testing",
"Categories",
"Values",
dataset1,
PlotOrientation.VERTICAL,
true, // legend
true, // tool tips
false // URLs
);
//make the chart have a white background
chart.setBackgroundPaint(Color.white);
//get the chart's plot
final CategoryPlot plot = chart.getCategoryPlot();
//color the plot
plot.setBackgroundPaint(Color.lightGray);
plot.setDomainGridlinePaint(Color.white);
plot.setRangeGridlinePaint(Color.white);
//make a stacked area renderer for the first dataset
final StackedAreaRenderer renderer1 = new StackedAreaRenderer();
renderer1.setEndType(AreaRendererEndType.LEVEL);
renderer1.setDefaultToolTipGenerator(new StandardCategoryToolTipGenerator());
//turn off the first data set that lets the stack float
renderer1.setSeriesPaint(0, new Color(Color.blue.getRed(), Color.blue.getGreen(), Color.blue.getBlue(), 0));
renderer1.setSeriesVisibleInLegend(0, false);
plot.setRenderer(0, renderer1);
plot.setRenderer(1, renderer1);
// plot.setDataset(2, dataset2);
// final StackedAreaRenderer renderer2 = new StackedAreaRenderer();
// renderer2.setEndType(AreaRendererEndType.LEVEL);
// renderer2.setDefaultToolTipGenerator(new StandardCategoryToolTipGenerator());
// renderer2.setSeriesPaint(2, new Color(Color.green.getRed(), Color.green.getGreen(), Color.green.getBlue(), 0));
// renderer2.setSeriesVisibleInLegend(2, false);
// renderer1.setSeriesPaint(2, new Color(Color.green.getRed(), Color.green.getGreen(), Color.green.getBlue(), 0));
// renderer1.setSeriesPaint(3, new Color(Color.black.getRed(), Color.black.getGreen(), Color.black.getBlue(), 255));
// renderer1.setSeriesVisibleInLegend(2, false);
// plot.setRenderer(2, renderer2);
// plot.setRenderer(3, renderer2);
// plot.setRenderer(2, renderer1);
// plot.setRenderer(3, renderer1);
plot.setDomainAxisLocation(AxisLocation.BOTTOM_OR_RIGHT);
plot.getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.DOWN_45);
plot.setDomainCrosshairVisible(true);
plot.setRangeCrosshairVisible(true);
return chart;
}
public static void main(String[] args) {
final DifferenceWithCategories demo = new DifferenceWithCategories("Diference With Categories");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
}
version 1
If I uncomment the sections of code for dataset2 and renderer2 then I get some weird results where, I have three areas present and three items listed in the legend.
version 2
If I uncomment the sections of code for dataset2 and renderer1 the I get what I think is close to what I want but, the area for both is red and the legend on both is Second which is not present for dataset2.
Does anyone know how I can get the coloring of version 1 but the area sets of version 2?

I found out how to get what I'm looking for. The issue comes from the renderer needing to know the index of the datasets relative to itself vs index of the datasets relative to the plot.
So it was fixed with a second renderer using dataset indexing relative to itself when the renderer is added to the plot.
Code with expected outputs:
import java.awt.Dimension;
import java.util.List;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.labels.StandardCategoryToolTipGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.AreaRendererEndType;
import org.jfree.chart.renderer.category.StackedAreaRenderer;
import org.jfree.chart.ui.ApplicationFrame;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.ui.RefineryUtilities;
/**
*
* #author lemming622
*/
public class DifferenceWithCategories extends ApplicationFrame{
public DifferenceWithCategories(String title){
super(title);
final JFreeChart chart = createChart();
final ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new Dimension(500,270));
setContentPane(chartPanel);
}
/**
* Returns a sample dataset.
*
* #return The dataset.
*/
private CategoryDataset createDataset1() {
// row keys...
String series1 = "First";
// column keys...
String category1 = "Category 1";
String category2 = "Category 2";
String category3 = "Category 3";
String category4 = "Category 4";
String category5 = "Category 5";
// create the dataset...
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(4.0, series1, category1);
dataset.addValue(4.0, series1, category2);
dataset.addValue(3.0, series1, category3);
dataset.addValue(5.0, series1, category4);
dataset.addValue(5.0, series1, category5);
return dataset;
}
/**
* Returns a sample dataset.
*
* #return The dataset.
*/
private CategoryDataset createDataset2() {
// row keys...
String series2 = "Second";
// column keys...
String category1 = "Category 1";
String category2 = "Category 2";
String category3 = "Category 3";
String category4 = "Category 4";
String category5 = "Category 5";
// create the dataset...
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(5.0, series2, category1);
dataset.addValue(7.0, series2, category2);
dataset.addValue(6.0, series2, category3);
dataset.addValue(8.0, series2, category4);
dataset.addValue(6.0, series2, category5);
return dataset;
}
/**
* Returns a sample dataset.
*
* #return The dataset.
*/
private CategoryDataset createDataset3() {
// row keys...
String series3 = "Third";
// column keys...
String category1 = "Category 1";
String category2 = "Category 2";
String category3 = "Category 3";
String category4 = "Category 4";
String category5 = "Category 5";
// create the dataset...
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(1.0, series3, category1);
dataset.addValue(3.0, series3, category2);
dataset.addValue(2.0, series3, category3);
dataset.addValue(3.0, series3, category4);
dataset.addValue(4.0, series3, category5);
return dataset;
}
private CategoryDataset merge4StackedDataset(CategoryDataset d1, CategoryDataset d2){
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
List<Comparable> columnKeys = d1.getColumnKeys();
List<Comparable> d1RowKeys = d1.getRowKeys();
List<Comparable> d2RowKeys = d2.getRowKeys();
double minValue, maxValue;
for (Comparable columnKey : columnKeys) {
for (Comparable rowKey : d1RowKeys) {
for (Comparable d2RowKey : d2RowKeys) {
minValue = Math.min(d1.getValue(rowKey, columnKey).doubleValue(),d2.getValue(d2RowKey, columnKey).doubleValue());
maxValue = Math.max(d1.getValue(rowKey, columnKey).doubleValue(),d2.getValue(d2RowKey, columnKey).doubleValue());
dataset.addValue(minValue, rowKey, columnKey);
dataset.addValue(maxValue - minValue, d2RowKey, columnKey);
// dataset.addValue(d2.getValue(d2RowKey, columnKey).doubleValue(), d2RowKey, columnKey);
}
}
}
return dataset;
}
private JFreeChart createChart() {
CategoryDataset dataset1 = merge4StackedDataset(createDataset1(), createDataset2());
CategoryDataset dataset2 = merge4StackedDataset(createDataset1(), createDataset3());
//create chart with empty dataset
final JFreeChart chart = ChartFactory.createAreaChart(
"Testing",
"Categories",
"Values",
dataset1,
PlotOrientation.VERTICAL,
true, // legend
true, // tool tips
false // URLs
);
//make the chart have a white background
chart.setBackgroundPaint(Color.white);
//get the chart's plot
final CategoryPlot plot = chart.getCategoryPlot();
//color the plot
plot.setBackgroundPaint(Color.lightGray);
plot.setDomainGridlinePaint(Color.white);
plot.setRangeGridlinePaint(Color.white);
//make a stacked area renderer for the first dataset
final StackedAreaRenderer renderer1 = new StackedAreaRenderer();
renderer1.setEndType(AreaRendererEndType.LEVEL);
renderer1.setDefaultToolTipGenerator(new StandardCategoryToolTipGenerator());
//turn off the first data set that lets the stack float
renderer1.setSeriesPaint(0, new Color(Color.blue.getRed(), Color.blue.getGreen(), Color.blue.getBlue(), 0));
renderer1.setSeriesVisibleInLegend(0, false);
plot.setRenderer(0, renderer1);
plot.setRenderer(1, renderer1);
plot.setDataset(2, dataset2);
final StackedAreaRenderer renderer2 = new StackedAreaRenderer();
renderer2.setEndType(AreaRendererEndType.LEVEL);
renderer2.setDefaultToolTipGenerator(new StandardCategoryToolTipGenerator());
renderer2.setSeriesPaint(0, new Color(Color.green.getRed(), Color.green.getGreen(), Color.green.getBlue(), 0));
renderer2.setSeriesVisibleInLegend(0, false);
plot.setRenderer(2, renderer2);
plot.setRenderer(3, renderer2);
plot.setDomainAxisLocation(AxisLocation.BOTTOM_OR_RIGHT);
plot.getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.DOWN_45);
plot.setDomainCrosshairVisible(true);
plot.setRangeCrosshairVisible(true);
return chart;
}
public static void main(String[] args) {
final DifferenceWithCategories demo = new DifferenceWithCategories("Diference With Categories");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
}

Related

How to create hollow shapes in JFreeChart Scatter Plot

JFreeChart version used: 1.5.0
I tried the following to obtain hollow shapes in a scatter plot:
PlotFrame.java file content:
package javaapplication1;
import javax.swing.JFrame;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
/**
*
* #author tarik
*/
public class PlotFrame extends javax.swing.JFrame {
public static void main(String[] argv) {
PlotFrame plotFrame = new PlotFrame();
plotFrame.setVisible(true);
}
/**
* Creates new form PlotFrame
*/
public PlotFrame() {
this.setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JFreeChart chart = createChart();
ChartPanel panel = new ChartPanel(chart);
this.add(panel);
pack();
}
private JFreeChart createChart() {
// Create dataset
XYDataset dataset = createDataset();
// Create chart
JFreeChart chart = ChartFactory.createScatterPlot(
"Boys VS Girls weight comparison chart",
"X-Axis", "Y-Axis", dataset);
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) chart.getXYPlot().getRenderer();
//renderer.setBaseShapesFilled(false);
renderer.setUseFillPaint(false);
return chart;
}
private XYDataset createDataset() {
XYSeriesCollection dataset = new XYSeriesCollection();
//Boys (Age,weight) series
XYSeries series1 = new XYSeries("Boys");
series1.add(1, 72.9);
series1.add(2, 81.6);
series1.add(3, 88.9);
series1.add(4, 96);
series1.add(5, 102.1);
series1.add(6, 108.5);
series1.add(7, 113.9);
series1.add(8, 119.3);
series1.add(9, 123.8);
series1.add(10, 124.4);
dataset.addSeries(series1);
//Girls (Age,weight) series
XYSeries series2 = new XYSeries("Girls");
series2.add(1, 72.5);
series2.add(2, 80.1);
series2.add(3, 87.2);
series2.add(4, 94.5);
series2.add(5, 101.4);
series2.add(6, 107.4);
series2.add(7, 112.8);
series2.add(8, 118.2);
series2.add(9, 122.9);
series2.add(10, 123.4);
dataset.addSeries(series2);
return dataset;
}
}
It did not work, the shapes are still filled.
Recall that Graphics2D can draw() the outline of a Shape as well as fill() its interior. By limiting rendering to draw(), #micro's approach is sound in this regard, but it assumes version 1.0.19. When migrating to version 1.5 and later, note that "many methods getBaseXXX()/setBaseXXX() have been renamed setDefaultXXX()/getDefaultXXX()." The correct formulation is illustrated below:
renderer.setDefaultShapesFilled(false);
renderer.setUseFillPaint(false);
Other changes:
Construct and manipulate Swing GUI objects only on the event dispatch thread.
Override getPreferredSize() to set the chart's initial preferred size.
As tested:
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
/**
* #see https://stackoverflow.com/q/58812592/230513
* #author trashgod
* #author tarik
*/
public class PlotFrame extends javax.swing.JFrame {
public static void main(String[] argv) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
PlotFrame plotFrame = new PlotFrame();
plotFrame.setLocationRelativeTo(null);
plotFrame.setVisible(true);
}
});
}
/**
* Creates new form PlotFrame
*/
public PlotFrame() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JFreeChart chart = createChart();
ChartPanel panel = new ChartPanel(chart){
#Override
public Dimension getPreferredSize() {
return new Dimension(640, 480);
}
};
this.add(panel);
this.pack();
}
private JFreeChart createChart() {
// Create dataset
XYDataset dataset = createDataset();
// Create chart
JFreeChart chart = ChartFactory.createScatterPlot(
"Boys VS Girls weight comparison chart",
"X-Axis", "Y-Axis", dataset);
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) chart.getXYPlot().getRenderer();
renderer.setDefaultShapesFilled(false);
renderer.setUseFillPaint(false);
return chart;
}
private XYDataset createDataset() {
XYSeriesCollection dataset = new XYSeriesCollection();
//Boys (Age,weight) series
XYSeries series1 = new XYSeries("Boys");
series1.add(1, 72.9);
series1.add(2, 81.6);
series1.add(3, 88.9);
series1.add(4, 96);
series1.add(5, 102.1);
series1.add(6, 108.5);
series1.add(7, 113.9);
series1.add(8, 119.3);
series1.add(9, 123.8);
series1.add(10, 124.4);
dataset.addSeries(series1);
//Girls (Age,weight) series
XYSeries series2 = new XYSeries("Girls");
series2.add(1, 72.5);
series2.add(2, 80.1);
series2.add(3, 87.2);
series2.add(4, 94.5);
series2.add(5, 101.4);
series2.add(6, 107.4);
series2.add(7, 112.8);
series2.add(8, 118.2);
series2.add(9, 122.9);
series2.add(10, 123.4);
dataset.addSeries(series2);
return dataset;
}
}
From source code:
if (getItemShapeFilled(series, item)) {
if (this.useFillPaint) {
g2.setPaint(getItemFillPaint(series, item));
}
else {
g2.setPaint(getItemPaint(series, item));
}
g2.fill(shape);
}
For the first if there is no else, so we need the getItemShapeFilled to return false. It looks like this:
public boolean getItemShapeFilled(int series, int item) {
Boolean flag = getSeriesShapesFilled(series);
if (flag != null) {
return flag;
}
return this.baseShapesFilled;
}
Easiest way is to use this method:
public void setBaseShapesFilled(boolean flag) {
this.baseShapesFilled = flag;
fireChangeEvent();
}
So the actual code is:
import javax.swing.JFrame;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
/**
*
* #author tarik
*/
public class PlotFrame extends javax.swing.JFrame {
public static void main(String[] argv) {
PlotFrame plotFrame = new PlotFrame();
plotFrame.setVisible(true);
}
/**
* Creates new form PlotFrame
*/
public PlotFrame() {
this.setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JFreeChart chart = createChart();
ChartPanel panel = new ChartPanel(chart);
this.add(panel);
pack();
}
private JFreeChart createChart() {
// Create dataset
XYDataset dataset = createDataset();
// Create chart
JFreeChart chart = ChartFactory.createScatterPlot(
"Boys VS Girls weight comparison chart",
"X-Axis", "Y-Axis", dataset);
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) chart.getXYPlot().getRenderer();
renderer.setBaseShapesFilled(false);
renderer.setUseFillPaint(false);
return chart;
}
private XYDataset createDataset() {
XYSeriesCollection dataset = new XYSeriesCollection();
//Boys (Age,weight) series
XYSeries series1 = new XYSeries("Boys");
series1.add(1, 72.9);
series1.add(2, 81.6);
series1.add(3, 88.9);
series1.add(4, 96);
series1.add(5, 102.1);
series1.add(6, 108.5);
series1.add(7, 113.9);
series1.add(8, 119.3);
series1.add(9, 123.8);
series1.add(10, 124.4);
dataset.addSeries(series1);
//Girls (Age,weight) series
XYSeries series2 = new XYSeries("Girls");
series2.add(1, 72.5);
series2.add(2, 80.1);
series2.add(3, 87.2);
series2.add(4, 94.5);
series2.add(5, 101.4);
series2.add(6, 107.4);
series2.add(7, 112.8);
series2.add(8, 118.2);
series2.add(9, 122.9);
series2.add(10, 123.4);
dataset.addSeries(series2);
return dataset;
}
}
My result is:
Isn't that what you meant?

How to draw a linechart on click in JFreeChart?

I am able to draw LineChart using JFreeChart. I would like to know how to draw linechart with legends. The place where I click should be dynamaically updated in the JFreeChart.
I have mentioned a image here to explain what I Mean.
In the Image I am able draw the black line what I want is the red line to be drawn on click. Can anybody suggest me something related to this?
Thanks in advance
Here is the sample code. In this I have 3 Series. and I am adding onclick datapoints to second series.
import com.sun.javafx.geom.Point2D;
import com.sun.javafx.scene.paint.GradientUtils.Point;
import java.awt.Color;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
public class ChartDemo extends ApplicationFrame implements ChartMouseListener {
/**
* Creates a new demo.
*
* #param title the frame title.
*/
public static ChartPanel chartPanel = null;
public static JFreeChart chart = null;
public static XYSeries series1,series2;
public ChartDemo(final String title) {
super(title);
final XYDataset dataset = createDataset();
final JFreeChart chart = createChart(dataset);
chartPanel = new ChartPanel(chart);
chartPanel.addChartMouseListener(this);
chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
setContentPane(chartPanel);
}
/**
* Creates a sample dataset.
*
* #return a sample dataset.
*/
private XYDataset createDataset() {
series1 = new XYSeries("First");
series1.add(1.0, 1.0);
series1.add(2.0, 4.0);
series1.add(3.0, 3.0);
series1.add(4.0, 5.0);
series1.add(5.0, 5.0);
series1.add(6.0, 7.0);
series1.add(7.0, 7.0);
series1.add(8.0, 8.0);
series2 = new XYSeries("Second");
series2.add(1.0, 5.0);
series2.add(2.0, 7.0);
series2.add(3.0, 6.0);
series2.add(4.0, 8.0);
series2.add(5.0, 4.0);
series2.add(6.0, 4.0);
series2.add(7.0, 2.0);
series2.add(8.0, 1.0);
final XYSeries series3 = new XYSeries("Third");
series3.add(3.0, 4.0);
series3.add(4.0, 3.0);
series3.add(5.0, 2.0);
series3.add(6.0, 3.0);
series3.add(7.0, 6.0);
series3.add(8.0, 3.0);
series3.add(9.0, 4.0);
series3.add(10.0, 3.0);
final XYSeriesCollection dataset = new XYSeriesCollection();
dataset.addSeries(series1);
dataset.addSeries(series2);
dataset.addSeries(series3);
return dataset;
}
/**
* Creates a chart.
*
* #param dataset the data for the chart.
*
* #return a chart.
*/
private JFreeChart createChart(final XYDataset dataset) {
// create the chart...
chart = ChartFactory.createXYLineChart(
"Chart Demo", // chart title
"X", // x axis label
"Y", // y axis label
dataset, // data
PlotOrientation.VERTICAL,
true, // include legend
true, // tooltips
false // urls
);
chart.setBackgroundPaint(Color.white);
final XYPlot plot = chart.getXYPlot();
plot.setBackgroundPaint(Color.lightGray);
// plot.setAxisOffset(new Spacer(Spacer.ABSOLUTE, 5.0, 5.0, 5.0, 5.0));
plot.setDomainGridlinePaint(Color.white);
plot.setRangeGridlinePaint(Color.white);
final XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
renderer.setSeriesLinesVisible(0, false);//to disable line on the graph
renderer.setSeriesShapesVisible(2, false);//to disable shape on the graph
plot.setRenderer(renderer);
final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
return chart;
}
public static void main(final String[] args)
{
final ChartDemo demo = new ChartDemo("Chart Demo");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
#Override
public void chartMouseClicked(ChartMouseEvent cme)
{
int mouseX = cme.getTrigger().getX();
int mouseY = cme.getTrigger().getY();
System.out.println("x = " + mouseX + ", y = " + mouseY);
java.awt.geom.Point2D p = chartPanel.translateScreenToJava2D(
new java.awt.Point(mouseX, mouseY));
XYPlot plot = (XYPlot) chart.getPlot();
System.out.println("Mouse clicked!!!!!");
Rectangle2D plotArea = this.chartPanel.getChartRenderingInfo().getPlotInfo().getDataArea();
ValueAxis domainAxis = plot.getDomainAxis();
org.jfree.chart.ui.RectangleEdge domainAxisEdge = plot.getDomainAxisEdge();
ValueAxis rangeAxis = plot.getRangeAxis();
org.jfree.chart.ui.RectangleEdge rangeAxisEdge = plot.getRangeAxisEdge();
double chartX = domainAxis.java2DToValue(p.getX(), plotArea,
domainAxisEdge);
double chartY = rangeAxis.java2DToValue(p.getY(), plotArea,
rangeAxisEdge);
System.out.println("Chart: x = " + chartX + ", y = " + chartY);
series2.add(chartX, chartY);
}
#Override
public void chartMouseMoved(ChartMouseEvent cme)
{
if(cme.getTrigger().getButton() == MouseEvent.BUTTON1)
{
}
}
}

Disable right click menu of JFreeChart

I want to disable the right click menu of JFreeChart.
I tried chartPanel.setPopupMenu(null), but it didn't work.
The following example creates a simple XYPlot with "panel.setPopupMenu( null )" disabling the popup Menu.
`
public class DisableChartPopupMenu extends ApplicationFrame {
public DisableChartPopupMenu(String title) {
super(title);
}
public static void main(final String[] args) {
(new DisableChartPopupMenu("example")).createChartNoPopupMenu();
}
public void createChartNoPopupMenu(){
final XYSeries series1 = new XYSeries("Series 1");
series1.add(10.0, 12353.3);
series1.add(20.0, 13734.4);
series1.add(30.0, 14525.3);
series1.add(40.0, 13984.3);
final XYSeriesCollection collection = new XYSeriesCollection();
collection.addSeries(series1);
final XYItemRenderer renderer1 = new StandardXYItemRenderer();
final NumberAxis rangeAxis1 = new NumberAxis("Range 1");
final XYPlot subplot1 = new XYPlot( collection, null, rangeAxis1, renderer1);
final CombinedDomainXYPlot plot = new CombinedDomainXYPlot(new NumberAxis("Domain"));
plot.add(subplot1, 1);
JFreeChart chart = new JFreeChart(" Demo", JFreeChart.DEFAULT_TITLE_FONT, plot, true);
final ChartPanel panel = new ChartPanel(chart, true, true, true, false, true);
panel.setPopupMenu( null );
setContentPane(panel); pack(); setVisible(true);
}
}
`

JfreeChart XYAreaChart draw shape at each point [duplicate]

I am using JFreeChart XYPLot for plotting a XYData set with different labels . I have created different XYSeries objects for different labels so that I can have different colors for different labels . Now I need to require the change the shapes of specific points(test data) in each XYDataSeries as below .
In the above plotting , there are two different XYSeries with blue and red color . Out of these two I need to change the shapes of some points(test data) to X instead of circle . Is it possible in JFreeChart. This post explained on how to do it for whole data set , but I want to change only specific points
Below is the code I have written so far
public static Map<String, XYSeries> createXYSeries(Data[] dataSet){
Map<String,XYSeries> xySeries = new HashMap<String, XYSeries>();
for(Data data : dataSet){
if(xySeries.get(data.actualLabel) == null){
xySeries.put(data.actualLabel, new XYSeries(data.actualLabel));
}
xySeries.get(data.actualLabel).add(data.dimensionValues[0],data.dimensionValues[1]);
}
return xySeries;
}
public XYDataset createXYSeriesCollection(Map<String, XYSeries> plottingDataSet) {
XYSeriesCollection xySeriesCollection = new XYSeriesCollection();
for (String key : plottingDataSet.keySet()) {
xySeriesCollection.addSeries(plottingDataSet.get(key));
}
return xySeriesCollection;
}
private ChartPanel createPlottingPanel(String title,
Map<String, XYSeries> plottingDataSet) {
JFreeChart jfreechart = ChartFactory.createScatterPlot(title, "X", "Y",
createSampleData(plottingDataSet), PlotOrientation.VERTICAL,
true, true, false);
XYPlot xyPlot = (XYPlot) jfreechart.getPlot();
xyPlot.setDomainCrosshairVisible(true);
xyPlot.setRangeCrosshairVisible(true);
xyPlot.setBackgroundPaint(Color.white);
return new ChartPanel(jfreechart);
}
Note : I am trying to plot the KNearestNeighbors results .(Circles for train data and X for test data)
ChartFactory.createScatterPlot() instantiates an XYLineAndShapeRenderer. You can replace the renderer with one that lets you selectively replace the Shape returned by getItemShape(), as shown below.
xyPlot.setRenderer(new XYLineAndShapeRenderer(false, true) {
#Override
public Shape getItemShape(int row, int col) {
if (row == 0 & col == N) {
return ShapeUtilities.createDiagonalCross(5, 2);
} else {
return super.getItemShape(row, col);
}
}
});
Complete example, as run:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Shape;
import java.util.*;
import javax.swing.JFrame;
import org.jfree.chart.*;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.util.ShapeUtilities;
/**
* #see http://stackoverflow.com/a/20359200/230513
* #see http://stackoverflow.com/a/6669529/230513
*/
public class ScatterShape extends JFrame {
private static final int N = 8;
private static final int SIZE = 345;
private static final String title = "Scatter Shape Demo";
private static final Random rand = new Random();
private final XYSeries series = new XYSeries("Data");
public ScatterShape(String s) {
super(s);
final ChartPanel chartPanel = createDemoPanel();
this.add(chartPanel, BorderLayout.CENTER);
}
private ChartPanel createDemoPanel() {
JFreeChart chart = ChartFactory.createScatterPlot(
title, "X", "Y", createSampleData(),
PlotOrientation.VERTICAL, true, true, false);
XYPlot xyPlot = (XYPlot) chart.getPlot();
xyPlot.setDomainCrosshairVisible(true);
xyPlot.setRangeCrosshairVisible(true);
xyPlot.setRenderer(new XYLineAndShapeRenderer(false, true) {
#Override
public Shape getItemShape(int row, int col) {
if (row == 0 & col == N) {
return ShapeUtilities.createDiagonalCross(5, 2);
} else {
return super.getItemShape(row, col);
}
}
});
adjustAxis((NumberAxis) xyPlot.getDomainAxis(), true);
adjustAxis((NumberAxis) xyPlot.getRangeAxis(), false);
xyPlot.setBackgroundPaint(Color.white);
return new ChartPanel(chart) {
#Override
public Dimension getPreferredSize() {
return new Dimension(SIZE, SIZE);
}
};
}
private void adjustAxis(NumberAxis axis, boolean vertical) {
axis.setRange(-3.0, 3.0);
axis.setTickUnit(new NumberTickUnit(0.5));
axis.setVerticalTickLabels(vertical);
}
private XYDataset createSampleData() {
XYSeriesCollection xySeriesCollection = new XYSeriesCollection();
for (int i = 0; i < N * N; i++) {
series.add(rand.nextGaussian(), rand.nextGaussian());
}
xySeriesCollection.addSeries(series);
return xySeriesCollection;
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
ScatterShape demo = new ScatterShape(title);
demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
demo.pack();
demo.setLocationRelativeTo(null);
demo.setVisible(true);
}
});
}
}

JFreeChart Horizontal Charts

I'm using CombinedDomainXYPlot to plot the charts. I have another requirement where, I need to show the two charts horizontally.
Currently i'm having only one chart. what i need is, i need two charts in the first row.
like Chart1 Chart2
Code:
CombinedDomainXYPlot plot = new CombinedDomainXYPlot();
plot.add(getChart1(), 2);
plot.add(getChart2(), 2);
It is giving only one chart in the first row. and second chart2 in the another row.
Is there any way I can make these two charts into single row?
Edit: Actually I wanted it like your ThermometerDemo example. For that you have used JPanel, but here I'm using JFrame.
I wanted it like your ThermometerDemo example.
Based on this example, the code below adds two panels to a GridLayout(1, 0). Each panel includes it's own chart and control panel.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.Random;
import javax.swing.*;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CombinedDomainXYPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
/**
* #see https://stackoverflow.com/a/20243624/230513
* #see https://stackoverflow.com/q/11870416/230513
*/
public class CombinedPlot {
private static final int MAX = 3;
private static final Random rand = new Random();
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
init();
}
});
}
private static void init() {
JFrame frame = new JFrame("Combined Plot Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout(1, 0));
frame.add(createPanel());
frame.add(createPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static JPanel createPanel() {
JPanel p = new JPanel(new BorderLayout());
XYItemRenderer renderer = new StandardXYItemRenderer();
XYPlot plot1 = new XYPlot(
generateData(), null, new NumberAxis("Range 1"), renderer);
XYPlot plot2 = new XYPlot(
generateData(), null, new NumberAxis("Range 2"), renderer);
final CombinedDomainXYPlot plot
= new CombinedDomainXYPlot(new NumberAxis("Domain"));
plot.add(plot1);
plot.add(plot2);
plot.setOrientation(PlotOrientation.VERTICAL);
JFreeChart chart = new JFreeChart(
"Combined Plots", JFreeChart.DEFAULT_TITLE_FONT, plot, false);
ChartPanel chartPanel = new ChartPanel(chart) {
#Override
public Dimension getPreferredSize() {
return new Dimension(320, 320);
}
};
JPanel controlPanel = new JPanel();
controlPanel.add(new JButton(new UpdateAction(plot, 0)));
controlPanel.add(new JButton(new UpdateAction(plot, 1)));
p.add(chartPanel, BorderLayout.CENTER);
p.add(controlPanel, BorderLayout.SOUTH);
return p;
}
private static class UpdateAction extends AbstractAction {
private final XYPlot plot;
public UpdateAction(CombinedDomainXYPlot plot, int i) {
super("Update plot " + (i + 1));
this.plot = (XYPlot) plot.getSubplots().get(i);
}
#Override
public void actionPerformed(ActionEvent e) {
plot.setDataset(CombinedPlot.generateData());
}
}
private static XYSeriesCollection generateData() {
XYSeriesCollection data = new XYSeriesCollection();
for (int i = 0; i < MAX; i++) {
data.addSeries(generateSeries("Series " + (i + 1)));
}
return data;
}
private static XYSeries generateSeries(String key) {
XYSeries series = new XYSeries(key);
for (int i = 0; i < 16; i++) {
series.add(rand.nextGaussian(), rand.nextGaussian());
}
return series;
}
}

Resources