Primo di due articoli sulla descrizione delle API di JFreeChart, una libreria Java Open Source che consente la generazione dinamica di grafici a partire da una fonte dati e di esportarli nei formati PNG e JPEG, anche da Servlet.
Introduzione
JFreeChart è una libreria Java Open Source (rilasciata sotto licenza LGPL) per la generazione dinamica di grafici a partire da una fonte dati. Può essere utilizzata sia in applicazioni Java standalone che web (quindi anche nelle Servlet e nelle JSP).
Caratteristiche principali della libreria
Tramite JFreeChart è possibile generare grafici di svariati tipi, quali grafici a torta, istogrammi, line chart, time series chart, scatter plot chart, Gantt, etc. Nelle figure 1, 2, 3 e 4 vengono mostrati quattro esempi dei diversi tipi realizzabili tramite JFreeChart.
Tra le caratteristiche principali di JFreeChart vale la pena di ricordare anche le seguenti:
- grafici realizzabili in maniera sia bidimensionale che tridimensionale;
- export diretto dei grafici nei formati immagine PNG (Portable Network Graphic) e JPEG (Joint Photografic Experts Group);
- possibilità di aggiungere tooltip ai grafici;
- possibilità di implementare uno zoom interattivo sui grafici;
- gestione degli eventi del mouse sui grafici;
- generazione di Image Map HTML;
- export dei grafici in PDF tramite iText (http://www.lowagie.com/iText/);
- export dei grafici in SVG tramite Batik (http://xmlgraphics.apache.org/batik/);
- accesso ai dati provenienti da sorgenti di diversa natura (database, file, etc.) tramite interfacce dataset dedicate già disponibili nella libreria.
La versione più recente di JFreeChart è la 1.0.1. Necessita della versione 1.3 o superiore del JDK. Ha bisogno anche di JCommon 1.0.0 (http://www.jfree.org/jcommon/index.php), un insieme di utility già incluso comunque nell‘archivio scaricabile dal sito ufficiale di JFreeChart (http://www.jfree.org/jfreechart/index.php).
Nell‘implementazione di un‘applicazione Java che ha bisogno di generare dei grafici a runtime solo al momento in cui arrivano effettivamente i dati, utilizzare JFreeChart porta dei vantaggi rispetto al ricorso alle sole API Sun native. Innanzitutto si ha la possibilità di esportare i grafici anche nel formato PNG, oltre che JPEG. Si ha poi la possibilità di utilizzare le API allo stesso modo sia in una Servlet che in una qualsiasi altra classe Java. E soprattutto, si ha già a disposizione un insieme di dataset e un insieme di API per la loro gestione che evitano di doverne implementare di nuovi.
JFreeChart è integrato anche in JasperReports per l‘inclusione di grafici nei report generati con quest‘ultima libreria.
A prescindere dal tipo, la generazione di un grafico tramite JFreeChart prevede sempre le seguenti azioni:
- creazione e popolamento di un Dataset;
- creazione di un oggetto di tipo JFreeChart tramite il corrispondente metodo della classe org.jfree.chart.ChartFactory;
- impostazione degli attributi del diagramma tramite una delle classi plot del package org.jfree.chart.plot;
- rendering del grafico tramite una delle classi del package org.jfree.chart.renderer;
- definizione dell‘asse delle ascisse tramite una delle classi del package org.jfree.chart.axis.
Un primo esempio di applicazione
Vediamo adesso un esempio pratico di utilizzo. Creiamo una classe Java la quale, a runtime, genererà un Time Series chart e lo visualizzerà in una interfaccia Swing. Un Time Series chart è un grafico in cui l‘asse delle ascisse è un asse temporale. Chiamiamo la classe di esempio TimeSeriesExample. Essa estende la classe org.jfree.ui.ApplicationFrame. Quest‘ultima, facente parte di JCommon, eredita tutte le caratteristiche di javax.swing.JFrame (essendone una specializzazione) e prevede già la gestione degli eventi della finestra dell‘applicazione.
TimeSeriesExample dovrà fare l‘overriding del costruttore di ApplicationFrame:
public TimeSeriesExample( String pStrTitle ) {super( pStrTitle );ChartPanel lChartPanel = (ChartPanel)createDemoPanel();lChartPanel.setPreferredSize( new java.awt.Dimension( 500, 270 ) );lChartPanel.setMouseZoomable( true, false );setContentPane( lChartPanel );}
Il parametro in ingresso al costruttore è il title del frame. Il metodo createDemoPanel costruisce il Panel (org.jfree.chart.ChartPanel) destinato a contenere il grafico:
public static JPanel createDemoPanel() {JFreeChart lChart = createChart( createDataset() );return new ChartPanel( lChart );}
Il grafico vero e proprio è un oggetto di tipo org.jfree.chart.JFreeChart. Viene creato dal metodo createChart a partire da un Dataset popolato dal metodo createDataset:
private static XYDataset createDataset() {TimeSeries lTimeSeries1 = new TimeSeries( "MokaByte Index", Month.class );lTimeSeries1.add( new Month( 1, 2005 ), 181.8 );lTimeSeries1.add( new Month( 2, 2005), 167.3 );lTimeSeries1.add( new Month( 3, 2005 ), 153.8 );lTimeSeries1.add( new Month( 4, 2005 ), 167.6 );lTimeSeries1.add( new Month( 5, 2005 ), 158.8 );lTimeSeries1.add( new Month( 6, 2005 ), 148.3 );lTimeSeries1.add( new Month( 7, 2005), 153.9 );lTimeSeries1.add( new Month( 8, 2005 ), 142.7 );lTimeSeries1.add( new Month( 9, 2005 ), 123.2 );lTimeSeries1.add( new Month( 10, 2005 ), 131.8 );lTimeSeries1.add( new Month( 11, 2005 ), 139.6 );lTimeSeries1.add( new Month( 12, 2005 ), 142.9 );lTimeSeries1.add( new Month( 1, 2006), 138.7 );lTimeSeries1.add( new Month( 2, 2006 ), 137.3 );lTimeSeries1.add( new Month( 3, 2006 ), 143.9 );lTimeSeries1.add( new Month( 4, 2006 ), 139.8 );TimeSeries lTimeSeries2 = new TimeSeries( "MokaCode Index", Month.class );lTimeSeries2.add( new Month( 1, 2005 ), 129.6 );lTimeSeries2.add( new Month( 2, 2005), 123.2 );lTimeSeries2.add( new Month( 3, 2005 ), 117.2 );lTimeSeries2.add( new Month( 4, 2005 ), 124.1 );lTimeSeries2.add( new Month( 5, 2005 ), 122.6 );lTimeSeries2.add( new Month( 6, 2005 ), 119.2 );lTimeSeries2.add( new Month( 7, 2005 ), 116.5 );lTimeSeries2.add( new Month( 8, 2005 ), 112.7 );lTimeSeries2.add( new Month( 9, 2005 ), 101.5 );lTimeSeries2.add( new Month( 10, 2005 ), 106.1 );lTimeSeries2.add( new Month( 11, 2005 ), 110.3 );lTimeSeries2.add( new Month( 12, 2005 ), 111.7 );lTimeSeries2.add( new Month( 1, 2006 ), 111.0 );lTimeSeries2.add( new Month( 2, 2006 ), 109.6 );lTimeSeries2.add( new Month( 3, 2006 ), 113.2 );lTimeSeries2.add( new Month( 4, 2006 ), 111.6 );TimeSeriesCollection lDataset = new TimeSeriesCollection();lDataset.addSeries( lTimeSeries1 );lDataset.addSeries( lTimeSeries2 );return lDataset;}
Il Dataset utilizzato è di tipo org.jfree.data.time.TimeSeriesCollection, specifico per le serie temporali. Questa classe implementa l‘interfaccia org.jfree.data.xy.XYDataset, dato che i Time Series chart sono una specializzazione degli XY Line chart. Nell‘esempio che stiamo costruendo il diagramma conterrà due curve relative, ciascuna relativa ad una serie temporale diversa. Entrambe vanno assegnate ad un unico Dataset.
Il grafico vero e proprio è generato dal metodo createChart. Un Chart viene creato invocando il metodo dedicato della classe org.jfree.chart.ChartFactory. Questa prevede un metodo di create specifico per ogni tipo di Chart previsto dalla libreria. Nel caso dell‘esempio:
// Creazione dell‘oggetto Chart tramite il ChartFactory.// I parametri in ingresso al metodo createTimeSeriesChart sono:// titolo// label per l‘asse delle ascisse// label per l‘asse delle ordinate// Dataset con i dati con cui popolare il grafico// boolean che indica se creare la legenda oppure no// boolean che indica se creare i tooltip oppure no// boolean che indica se creare dei collegamenti a punti del graficoJFreeChart lChart = ChartFactory.createTimeSeriesChart("Mokabyte Time Series Example","Date","Valori",pDataset,true,true,false);
Tramite la classe org.jfree.chart.plot.XYPlot dobbiamo impostare le proprietà del diagramma:
XYPlot lXYPlot = (XYPlot)lChart.getPlot();lXYPlot.setBackgroundPaint( Color.lightGray );lXYPlot.setDomainGridlinePaint( Color.white );lXYPlot.setRangeGridlinePaint( Color.white );lXYPlot.setAxisOffset( new RectangleInsets( 5.0, 5.0, 5.0, 5.0 ) );lXYPlot.setDomainCrosshairVisible( true );lXYPlot.setRangeCrosshairVisible( true );
Dall‘istanza di XYPlot ne ricaviamo una di org.jfree.chart.renderer.xy.XYItemRenderer per poter quindi eseguire il rendering delle due curve nel diagramma, visualizzando i marcatori dei punti:
XYItemRenderer lXYItemRenderer = lXYPlot.getRenderer();if ( lXYItemRenderer instanceof XYLineAndShapeRenderer ) {XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer)lXYItemRenderer;renderer.setBaseShapesVisible( true );renderer.setBaseShapesFilled( true );}
Infine dobbiamo impostare l‘asse delle ascisse. poiché nell‘esempio stiamo facendo riferimento a un Time Series chart, dobbiamo ricorrere ad un oggetto di tipo org.jfree.chart.axis.DateAxis (la classe del package org.jfree.chart.axis specifica per il caso in cui i valori dell‘asse delle ascisse siano date o time):
DateAxis lXYAxis = (DateAxis)lXYPlot.getDomainAxis();lXYAxis.setDateFormatOverride( new SimpleDateFormat( "MMM-yyyy" ) );
L‘esecuzione della classe produrrà un grafico come quello riportato in figura 5.
L‘esempio completo è allegato all‘articolo.
Per generare grafici diversi dai Times Series chart i passi da compiere sono analoghi a quelli di questo esempio.
Conclusioni
In questa prima parte sono state descritte le principali feature di JFreeChart ed è stato spiegato un primo esempio di utilizzo all‘interno di una applicazione Java standalone. Nella seconda ed ultima parte vedremo come utilizzare praticamente le API della libreria in un‘applicazione web e come generare grafici a partire da un Dataset popolato con valori recuperati da un database.
Bibliografia
[1] David Gilbert “The JFreeChart Class Library – Installation Guide”
http://www.jfree.org/jfreechart/index.php