retrieve data set having only a ChartPanel reference (Java + JFreeChart) - java

This question in partially related to my previous post on this subject.
I would like to know after a ChartPanel has been constructed :
public ChartPanel buildChart(){
XYSeriesCollection dataset = new XYSeriesCollection();
...
FreeChart chart = ChartFactory.createXYLineChart("line chart example",
"X", "Y", dataset, PlotOrientation.VERTICAL, true, true, false);
ChartPanel chartPanel = new ChartPanel(chart);
return chartPanel;
}
Can I retrieve the dataset used for generating chart, but having only a reference to chartPanel?
ChartPanel panel = buildChart();
panel.getDataset; //I'm looking for a way to retrieve the dataset, or XYSeriesCollection..
Is that possible? Can someone put me in the right direction?
thanks in advance

The easiest way is to make a dataset reference available to the view, as shown here. Alternatively, you can drill down from the ChartPanel, as suggested below.
ChartPanel chartPanel;
JFreeChart chart = chartPanel.getChart();
XYPlot plot = (XYPlot) chart.getPlot();
XYDataset data = plot.getDataset();

Related

How to change the type of the chart after creating it?

I created a graph of xy line chart by this code:
JFreeChart chart = ChartFactory.createXYLineChart(
"", // chart title
"Viscosity #25 C°", // x axis label
"Tg C°", // y axis label
dataset, // data
PlotOrientation.VERTICAL,
true, // include legend
true, // tooltips
false // urls
);
Now after I created it, I want to change the type to SpiderWebPlot. How to do this?
I tried to create in chart variable the spiderWebPlot, but it din't work.
Enclose your JFreeChart in a ChartPanel and invoke setChart() to replace the chart in the panel as the need arises. Complete examples are shown here and here. To change the chart panel's initial size, override getPreferredSize() as shown here.

Combining a BarChart and Linechart with J free chart

Hi im trying to create a chart that is a combination of a bar chart and a line chart in JFree chart. The bar chart is vs time and for each hour it will compare two (or more) different values.
The line chart uses the same scale as the bar chart and shows the overall trend of the data set.
You can plot each dataset on the same Plot, and use a different renderer for each dataset (for instance a BarRenderer and LineAndShapeRenderer). Below is a simplified example that generates some mock data values (1-9) and renders the same data as both bars and lines on the same ChartPanel.
//Mock data
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
int[] times = new int[]{1,2,3,4,5,6,7,8,9};
for ( int i = 0; i < times.length; i++ ){
dataset.addValue(times[i], "Time", "Hour" + String.valueOf(i+1));
}
//create the plot
CategoryPlot plot = new CategoryPlot();
//add the first dataset, and render as bar values
CategoryItemRenderer renderer = new BarRenderer();
plot.setDataset(0,dataset);
plot.setRenderer(0,renderer);
//add the second dataset, render as lines
CategoryItemRenderer renderer2 = new LineAndShapeRenderer();
plot.setDataset(1, dataset);
plot.setRenderer(1, renderer2);
//set axis
plot.setDomainAxis(new CategoryAxis("Time"));
plot.setRangeAxis(new NumberAxis("Value"));
And the resulting Chart:

Dynamic JFreeChart not redrawing on changes

I am making use of the JFreeChart library to plot the progress of a genetic algorithm in real time.
I'm using Swing for the UI. I have a panel where I draw all the various parameters for the algorithm, and a ChartPanel object. This object is drawn before I call the algorithm's search method (which updates the chart's XYSeries object at each generation), and at the end of the search, with all the values being accurately plotted.
According to the docs, the ChartPanel object is redrawn when its respective chart is updated. Obviously, the Swing panel itself isn't being redrawn until after the search is done, and I call repaint(), but what can I do to fix this?
This is the chart code:
public class XYSeriesDemo {
private static final long serialVersionUID = 1L;
private XYSeries series;
private JFreeChart chart;
public XYSeriesDemo(String str) {
series = new XYSeries(str);
XYSeriesCollection data = new XYSeriesCollection(series);
chart = createChart(data);
}
public XYSeries getSeries() {
return series;
}
public ChartPanel getChartPanel() {
return new ChartPanel(chart);
}
private JFreeChart createChart(final XYDataset data) {
JFreeChart chart = ChartFactory.createXYLineChart(
"Best fitness across generations",
"Generation",
"Fitness",
data,
PlotOrientation.VERTICAL,
true,
true,
false
);
XYPlot plot = chart.getXYPlot();
ValueAxis axis = plot.getDomainAxis();
axis.setAutoRange(true);
axis = plot.getRangeAxis();
axis.setAutoRange(true);
return chart;
}
}
In my panel constructor, I'm doing the following (this gets an empty chart drawn):
demo = new XYSeriesDemo("Best fitness");
this.add(demo.getChartPanel());
This is the method that the Swing frame calls in my JPanel object when the user orders a search:
public void solve() {
gen = new Random(seed);
XYSeries s = demo.getSeries();
GeneticAlgorithm ga = new GeneticAlgorithm(pop, crossoverP, mutationP,
eliteSize, maxGens, gen, s);
best = ga.search();
state = State.SOLVED;
time = ga.getTime() / 1E9;
}
At each generation, the search method in the algorithm simply does:
series.add(generation, pop.getBestFitness());
Thank you for reading.
Make sure that you are updating the dataset or series for the chart, ideally directly. The chart should refresh itself.
I would recommend buying the JFreeChart developer guide as it includes all sorts of examples including dynamic charts. The cost of the developer guide is what supports JFreeChart development.
I think you call your search process in EDT because of that it can't repaint components.
For updating your panel from code try to use SwingWorker, it can update UI and continue background process. You can find a lot of examples of using in Internet.
Or you can try to use Executors for background search process and updating UI.
I think this will work for you
JFreeChart jf = // Your JFreeChart chart Object.
ChartPanel chartPanel = new ChartPanel(jf);
myPanel.add(chartPanel);
myPanel.repaint();
myPanel.revalidate();

Partition pie chart into equal parts jfreechart

I have a data source in which there are three departments and each department has equal employees that are 8.
I want to make a pie chart using jFreeChart such that first we partition the pie into 3 equal parts for departments that is 120' for each department. Then in these partitions I want to show the sales of each employee. How can I do this in jFreeChart.
public class PieChart extends JFrame {
private PieDataset createDataset() {
DefaultPieDataset result = new DefaultPieDataset();
result.setValue("department1", 33.33);
result.setValue("department2", 33.33);
result.setValue("department3", 33.33);
return result;
}
private JFreeChart createChart(PieDataset dataset, String title) {
JFreeChart chart = ChartFactory.createPieChart3D(title, // chart title
dataset, // data
true, // include legend
true,
false);
PiePlot3D plot = (PiePlot3D) chart.getPlot();
plot.setStartAngle(290);
plot.setDirection(Rotation.CLOCKWISE);
plot.setForegroundAlpha(0.5f);
return chart;
}
}
public static void main(String[] args) {
PieChart demo = new PieChart("Comparison", "Which operating system are you using?");
demo.pack();
demo.setVisible(true);
}
PieChartDemo1 is a good starting point; focus on createDataset(); the full source is included in the distribution.
Addendum: How to further create partitions?
Ah, you want to sub-divide each 120° partition. DefaultPieDataset doesn't support a hierarchical structure directly, but you can use color in the PiePlot to highlight the grouping. Create related colors using Color.getHSBColor(), as shown here, and use setSectionPaint() to apply the colors accordingly.

set lower/upper bound in jfreechart bar charts

I'm a noob with jfreechart, and I have an app that creates a simple bar chart that is working well. The issue is, I want all the charts to show a range of 1 to 10. When the highest val in the chart is lower than that, that lower value will be the upper bound of the chart, and it will display in different increments. It wasn't obvious to me from the online notes where to change that....
DefaultCategoryDataset barDataSet = new DefaultCategoryDataset();
System.out.println("Setting values:");
barDataSet.setValue(rating.getFlavor(), "category", "Flavor");
barDataSet.setValue(rating.getBody(), "category", "Body");
barDataSet.setValue(rating.getAftertaste(), "category", "Aftertaste");
barDataSet.setValue(rating.getSweetness(), "category", "Sweetness");
barDataSet.setValue(rating.getFloral(), "category", "Floral");
barDataSet.setValue(rating.getSpice(), "category", "Spice");
JFreeChart chart = ChartFactory.createBarChart(null, // title
"category", // left heading
"score", // top heading
barDataSet, // dataset
PlotOrientation.HORIZONTAL,
false, // no idea what this is
true, // or this
false); // or this
System.out.println("setting bg color");
Color bgcolor = new Color(237, 232, 228);
chart.setBackgroundPaint(bgcolor);
CategoryPlot plot = chart.getCategoryPlot();
plot.setBackgroundPaint(new Color(112,112,112) );
thanks,
bp
You can change the displayed range via the axes. If i recall right, you can ask the JFreeChart instance for the XYPlot, with has a domain (x) and a range (y) axis. Both (when instances of NumberAxis) will have a setLowerBound(double) and setUpperBound(double) method.
chart.getXYPlot().getRangeAxis().setLowerBound(30.0);
chart.getXYPlot().getRangeAxis().setUpperBound(300.0);

Categories

Resources