In questo posto vediamo come generare 4 tipologie di grafici con JFreeChart, in particolare:
- Tachimetro (grafico a lancetta);
- Torta;
- Istogramma semplice;
- Istogramma multiplo.
Ho creato un semplice Java Project includendo le seguenti librerie nel classpath:
- jfreechart-1.0.9.jar;
- jcommon-1.0.12.jar;
- iText-2.0.8.jar.
Di seguito incollo la classe main principale, con dei metodi statici che generano delle immagini png per ciascun tipo grafico definito:
package chart.example;
import java.awt.BasicStroke;
import java.awt.Color;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.chart.labels.ItemLabelPosition;
import org.jfree.chart.labels.PieSectionLabelGenerator;
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.DialShape;
import org.jfree.chart.plot.MeterInterval;
import org.jfree.chart.plot.MeterPlot;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.CategoryItemRenderer;
import org.jfree.chart.title.LegendTitle;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.Range;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.general.DefaultValueDataset;
import org.jfree.ui.TextAnchor;
import com.lowagie.text.Font;
public class ChartCreator {
public static int myFontStyle = Font.UNDEFINED;
public static Font baseFont = new Font ( myFontStyle, 12, Font.NORMAL );
public static void main(String[] args) throws Exception {
creaGraficoATorta();
creaIstogrammaMultiplo();
creaTachimetro();
creaIstogrammaSemplice();
}
private static void creaGraficoATorta() throws Exception{
OutputStream fos=new FileOutputStream(new File("out/torta.png"));
String[] componenti=new String[]{"Inter","Milan","Rubentus"};
double[] valori=new double[]{18.0,18.0,28.0};
JFreeChart chart=creaGraficoATorta(componenti, valori, false);
ChartUtilities.writeChartAsPNG(fos, chart, 500, 300);
}
private static void creaIstogrammaMultiplo() throws Exception{
OutputStream fos=new FileOutputStream(new File("out/istoMul.png"));
double[] valori=new double[9];
valori[0]=20.0;
valori[1]=65.0;
valori[2]=15.0;
valori[3]=30.0;
valori[4]=50.0;
valori[5]=20.0;
valori[6]=25.0;
valori[7]=60.0;
valori[8]=15.0;
String[] componenti=new String[3];
componenti[0]="Lazio";
componenti[1]="Lombardia";
componenti[2]="Toscana";
String[] sottocomponenti=new String[3];
sottocomponenti[0]="Ricchi";
sottocomponenti[1]="Classe Media";
sottocomponenti[2]="Poveri";
JFreeChart chart=creaIstogramma(componenti,sottocomponenti, valori, "Ripartizione classi sociali", "Regioni", "Percentuali");
ChartUtilities.writeChartAsPNG(fos, chart, 500, 300);
}
private static void creaIstogrammaSemplice() throws Exception
{
OutputStream fos=new FileOutputStream(new File("out/isto.png"));
String[] componenti=new String[]{"Alto","Medio","Basso"};
double[] valori=new double[]{85.5,75.12,45.56};
JFreeChart chart=creaIstogramma(componenti, valori, "Andamenti", "", "");
ChartUtilities.writeChartAsPNG(fos, chart, 500, 300);
}
private static void creaTachimetro() throws Exception{
OutputStream fos=new FileOutputStream(new File("out/tachimetro.png"));
BigDecimal a=new BigDecimal(37.0);
BigDecimal b=new BigDecimal(49.0);
BigDecimal res=a.divide(b,2,RoundingMode.HALF_UP);
double v=res.doubleValue()*(double)100;
JFreeChart chart=creaTachimetro(new Double(v), "Esempio", "", Color.WHITE);
ChartUtilities.writeChartAsPNG(fos, chart, 500, 300);
}
public static JFreeChart creaTachimetro(Double valore, String titolo, String sottotitolo, Color bgcolor)
{
DefaultValueDataset ds = new DefaultValueDataset();
ds.setValue(valore);
MeterPlot plot = new MeterPlot(ds);
plot.setUnits("%");
plot.setRange(new Range(0, 100));
plot.setMeterAngle(210);
plot.addInterval(new MeterInterval("Intervallo1", new Range(90.0, 100.0), Color.LIGHT_GRAY, new BasicStroke(1.0f), new Color(255, 0, 0, 200)));
plot.addInterval(new MeterInterval("Intervallo2", new Range(80.0, 90.0), Color.LIGHT_GRAY, new BasicStroke(1.0f), new Color(255, 51, 0, 200)));
plot.addInterval(new MeterInterval("Intervallo3", new Range(70.0, 80.0), Color.LIGHT_GRAY, new BasicStroke(1.0f), new Color(255, 102, 0, 200)));
plot.addInterval(new MeterInterval("Intervallo4", new Range(60.0, 70.0), Color.LIGHT_GRAY, new BasicStroke(1.0f), new Color(255, 153, 0, 200)));
plot.addInterval(new MeterInterval("Intervallo5", new Range(50.0, 60.0), Color.LIGHT_GRAY, new BasicStroke(1.0f), new Color(255, 204, 0, 200)));
plot.addInterval(new MeterInterval("Intervallo6", new Range(40.0, 50.0), Color.LIGHT_GRAY, new BasicStroke(1.0f), new Color(255, 255, 0, 200)));
plot.addInterval(new MeterInterval("Intervallo7", new Range(30.0, 40.0), Color.LIGHT_GRAY, new BasicStroke(1.0f), new Color(192, 255, 0, 200)));
plot.addInterval(new MeterInterval("Intervallo8", new Range(20.0, 30.0), Color.LIGHT_GRAY, new BasicStroke(1.0f), new Color(128, 255, 0, 200)));
plot.addInterval(new MeterInterval("Intervallo9", new Range(10.0, 20.0), Color.LIGHT_GRAY, new BasicStroke(1.0f), new Color(64, 255, 0, 200)));
plot.addInterval(new MeterInterval("Intervallo10", new Range(0.0, 10.0), Color.LIGHT_GRAY, new BasicStroke(1.0f), new Color(0, 255, 0, 200)));
plot.setBackgroundPaint(bgcolor);
plot.setNeedlePaint(Color.BLACK);
plot.setDialBackgroundPaint(bgcolor);
plot.setDialOutlinePaint(bgcolor);
plot.setDialShape(DialShape.CIRCLE);
plot.setTickLabelsVisible(false);
plot.setTickSize(100.0);
plot.setTickPaint(Color.GRAY);
plot.setValueFont(new java.awt.Font("Dialog", Font.BOLD, 14));
plot.setValuePaint(Color.BLACK);
JFreeChart chart = new JFreeChart(null, null, plot, false);
chart.setBackgroundPaint(bgcolor);
if (!titolo.equals("")) {
TextTitle title = new TextTitle(titolo);
title.setFont(new java.awt.Font("Verdana", Font.BOLD, 12));
title.setPaint(new Color(0x2684B3));
chart.setTitle(title);
}
if (!sottotitolo.equals("")) {
TextTitle subtitle = new TextTitle(sottotitolo);
subtitle.setFont(new java.awt.Font("Verdana", java.awt.Font.ITALIC, 11));
subtitle.setPaint(new Color(0x2684B3));
chart.addSubtitle(subtitle);
}
return chart;
}
public static JFreeChart creaIstogramma(String[] componenti,String[] sottocomponenti,double[] valori,String titolo,String ascissa,String ordinata){
DefaultCategoryDataset cds=new DefaultCategoryDataset();
int j=0;
int cambioComponente=sottocomponenti.length;
String comp=componenti[j];
int sottoComp=0;
for(int i=0;i 1) {
for (int i = 0; i < componenti.length; i++) {
renderer.setSeriesItemLabelsVisible(i, true);
renderer.setSeriesItemLabelGenerator(i, new SeriesLabelGenerator());
}
} else {
renderer.setSeriesItemLabelsVisible(0, true);
renderer.setSeriesItemLabelGenerator(0, new LabelGenerator(null));
}
return chart;
}
public static JFreeChart creaIstogramma(String[] componenti,double[] valori,String titolo,String ascissa,String ordinata){
DefaultCategoryDataset cds=new DefaultCategoryDataset();
for(int i=0;i
Nel codice sono utilizzate due classi (LabelGenerator e SeriesLabelGenerator) che servono a mostrare nei grafici a torta e a istogramma semplice (LabelGenerator) e nel grafico a istogramma multiplo (SeriesLabelGenerator) i valori con le percentuali.
LabelGenerator
package chart.example;
import java.text.NumberFormat;
import org.jfree.chart.labels.AbstractCategoryItemLabelGenerator;
import org.jfree.chart.labels.CategoryItemLabelGenerator;
import org.jfree.data.category.CategoryDataset;
public class LabelGenerator extends AbstractCategoryItemLabelGenerator implements CategoryItemLabelGenerator {
private static final long serialVersionUID = 7389531138610633787L;
private Integer category;
private NumberFormat formatter = NumberFormat.getPercentInstance();
public LabelGenerator(int category) {
this(new Integer(category));
}
public LabelGenerator(Integer category) {
super("", NumberFormat.getInstance());
this.category = category;
}
public String generateLabel(CategoryDataset dataset, int series, int category ) {
String result = null;
double base = 0.0;
if (this.category != null) {
final Number b = dataset.getValue(series, this.category.intValue());
base = b.doubleValue();
}
else {
base = calculateSeriesTotal(dataset, series);
}
Number value = dataset.getValue(series, category);
if (value != null) {
final double v = value.doubleValue();
// you could apply some formatting here
result = " "+ value.toString() + " (" + this.formatter.format(v / base) + ")";
}
return result;
}
private double calculateSeriesTotal(CategoryDataset dataset, int series) {
double result = 0.0;
for (int i = 0; i < dataset.getColumnCount(); i++) {
Number value = dataset.getValue(series, i);
if (value != null) {
result = result + value.doubleValue();
}
}
return result;
}
}
SeriesLabelGenerator
package chart.example;
import java.text.NumberFormat;
import org.jfree.chart.labels.AbstractCategoryItemLabelGenerator;
import org.jfree.chart.labels.CategoryItemLabelGenerator;
import org.jfree.data.category.CategoryDataset;
public class SeriesLabelGenerator extends AbstractCategoryItemLabelGenerator implements CategoryItemLabelGenerator {
private static final long serialVersionUID = 7389531138610633787L;
private NumberFormat formatter = NumberFormat.getPercentInstance();
public SeriesLabelGenerator() {
super("", NumberFormat.getInstance());
}
public String generateLabel(CategoryDataset dataset, int series, int category ) {
String result = null;
double base = 0.0;
base = calculateCategoryTotal(dataset, category);
Number value = dataset.getValue(series, category);
if (value != null) {
final double v = value.doubleValue();
result = " "+ value.toString() + " (" + this.formatter.format(v / base) + ")";
}
return result;
}
private double calculateCategoryTotal(CategoryDataset dataset, int category) {
double result = 0.0;
for (int i = 0; i < dataset.getRowCount(); i++) {
Number value = dataset.getValue(i,category);
if (value != null) {
result = result + value.doubleValue();
}
}
return result;
}
}
Il risultato del codice è la generazione delle seguenti immagini:
Torta
Istogramma semplice
Istogramma multiplo
Grafico a lancetta