API per applicazioni

IV parte: JFreeChart, una libreria per disegnare graficidi

Continuiamo la carrellata tra API Java che possono risultare utili per affrontare specifici problemi. In questo numero passiamo in rassegna JFreeChart, una libreria Java pura che consente di realizzare grafici a partire da dati, utilizzando le tipologie di grafici più comuni e diffuse.

JFreeChart e le sue caratteristiche

JFreeChart è una libreria Java pura che ha come oggetto i grafici: tramite questa libreria, gli sviluppatori potranno facilmente incorporare grafici di qualità professionale nelle loro applicazioni. Le caratteristiche di JFreeChart sono:

  • una API  ben documentata, che supporta un'ampia gamma di tipi di grafici;
  • un design flessibile che è facile da estendere,  sia per le applicazioni lato server che lato client;
  • il supporto per molti tipi di output , tra cui Swing e componenti JavaFX , file immagine (tra cui PNG e JPEG) , e formati di file grafici vettoriali (inclusi PDF, EPS e SVG) ;
  • JFreeChart è open source o, più specificamente , "software libero". È distribuito in accordo con i termini della GNU Lesser General Public Licence (LGPL) che ne consente l'uso in applicazioni proprietarie.

Andando sul sito della libreria [1] è possibile scaricare nella sezione download il file JAR da includere nel vostro progetto.

Grafico a torta

Il diagramma circolare (comunemente indicato come "grafico a torta" o "diagramma a torta") si usa in statistica descrittiva per illustrare graficamente delle variabili quantitative misurate su classi di categorie; usando la "torta" e i suoi "spicchi" si evita di stabilire, anche involontariamente, un ordine che non esiste nelle categorie, cosa che accadrebbe invece utilizzando un istogramma.

Un diagramma circolare viene costruito dividendo un cerchio in spicchi: più lo spicchio è grande (vale a dire, maggiore è l'angolo), maggiore è la classe di frequenza rappresentata: in definitiva, come in un istogramma, c'è una proporzionalità diretta fra le aree e le frequenze da rappresentare.

Grafico a torta in JFreeChart

Supponiamo di voler costruire un grafico a torta che rispecchi la percentuale di marchi che sono nella gamma A, B, C, e D per CSC408: è un esempio con valori e nomi alla buona, usato nella documentazione della libreria. Il codice seguente illustra come sia possibile ottenere tale risultato in maniera piuttosto lineare.

public class PieChartExample {
            public static void main(String[] args) {
              // Creiamo un semplice grafico a torta
              DefaultPieDataset pieDataset = new DefaultPieDataset();
              
              // Imposto il valore dell'elemento A a 75
              pieDataset.setValue("A", new Integer(75));
              
              // Imposto il valore dell'elemento B a 10
              pieDataset.setValue("B", new Integer(10));
              
              // Imposto il valore dell'elemento C a 10
              pieDataset.setValue("C", new Integer(10));
              
              // Imposto il valore dell'elemento D a 5
              pieDataset.setValue("D", new Integer(5));
              
              JFreeChart chart = ChartFactory.createPieChart
              ("CSC408 Mark Distribution", // Titolo
              pieDataset, // Dataset
              true, // Mostra Legenda
              true, // Usa tooltips
              false // Dice se il grafico deve generare un URL?
              );
              
              try {
                ChartUtilities.saveChartAsJPEG(new File("C:\chart.jpg"), 
                      chart, 500,300);
              } catch (Exception e) {
              
              System.out.println("Problem occurred creating chart.");
              }
            }
}

 

 

 

Figura 1 - Il grafico a torta.

Grafico XY

Detti anche diagrammi a due variabili questi grafici rappresentano due variabili (x, y) su un piano cartesiano, dove sono individuate da una coppia di coordinate. Una variante più complessa è rappresentata da quei grafici che aggiungano una terza coordinata.

Grafico XY in JFreeChart

Nell'esempio che segue, costruiremo con JFreeChart una linea con la seguente serie di coordinate (x, y):

{(1, 1), (1, 2), (2, 1), (3, 9), (4, 10)}

Ecco il codice

public class XYChartExample {
            public static void main(String[] args) {
              // Creo un semplice grafico XY
              XYSeries series = new XYSeries("XYGraph");
              
              //Creo punti (X,Y)
              series.add(1, 1);
              series.add(1, 2);
              series.add(2, 1);
              series.add(3, 9);
              series.add(4, 10);
              
              // Aggiungo la serie di punti  al dataset
              XYSeriesCollection dataset = new XYSeriesCollection();
              dataset.addSeries(series);
              
              // Genero il grafico
              JFreeChart chart = ChartFactory.createXYLineChart(
              "XY Chart", // Titolo
              "x-axis",   // Etichetta asse X
              "y-axis",   // Etichetta asse Y 
              dataset,    // Dataset
              PlotOrientation.VERTICAL, // Orientamento grafico
              true,       // Mostra Legenda
              true,       // Usa tooltips
              false       // Dice se il grafico deve generare un URL
              );
      
              try {
                ChartUtilities.saveChartAsJPEG(new File("C:\chart.jpg"),
                   chart, 500, 300);
              } catch (IOException e) {
                System.err.println("Problem occurred creating chart.");
              }
            }
}

 

 

Figura 2 - Grafico per la rappresentazione di due variabili su un piano.

Grafico a barre

Il diagramma a colonne o a barre o "istogramma" si realizza utilizzando delle colonne come elementi rappresentativi di un dato. In pratica, il grafico si disegna usando tanti rettangoli quante sono le modalità da rappresentare. Tali rettangoli sono paralleli all'asse delle ordinate, hanno base fissa di dimensione uguale per ciascuna barra, ma l'altezza di ciascuna colonna è direttamente proporzionale al dato che essa rappresenta.

Istogramma in JFreeChart

Costruiamo un grafico a barre che confronta i profitti guadagnati dai seguenti ipotetici venditori: Jane, Tom, Jill, John, Fred.

public class BarChartExample {
            public static void main(String[] args) {
              // Creo  Diagramma a barre
              DefaultCategoryDataset dataset = new DefaultCategoryDataset();
              // Barre: valore, asseY, asseX
              dataset.setValue(6, "Profit", "Jane");
              dataset.setValue(7, "Profit", "Tom");
              dataset.setValue(8, "Profit", "Jill");
              dataset.setValue(5, "Profit", "John");
              dataset.setValue(12, "Profit", "Fred");
              JFreeChart chart 
              = ChartFactory.createBarChart("Comparison between Salesman",
                "Salesman", "Profit", dataset, PlotOrientation.VERTICAL,
                false, true, false);
              try {
                ChartUtilities.saveChartAsJPEG(new File("C:\chart.jpg"),
                       chart, 500, 300);
              } catch (IOException e) {
                System.err.println("Problem occurred creating chart.");
              }
            }
}

 

 

Figura 3 - L'istogramma o grafico a colonne.

Grafici con intervallo temporale

Una particolare versione del grafico a due variabili è quello in cui si rappresenta un andamento temporale. In tal caso, si uniscono i punti sul grafico, collocando per convenzione sull'asse orizzontale il tempo che scorre, mentre sull'asse verticale il valore di y indicherà il variare del valore.

Grafico con intervallo temporale in JFreeChart

Supponiamo di voler monitorare la popolazione di una piccola città su intervalli mensili.

public class TimeSeriesExample {
            public static void main(String[] args) {
              // Creo grafico ad intervallo temporale
              TimeSeries pop = new TimeSeries("Population", Day.class);
              // Data, Valore
              pop.add(new Day(10, 1, 2004), 100);
              pop.add(new Day(10, 2, 2004), 150);
              pop.add(new Day(10, 3, 2004), 250);
              pop.add(new Day(10, 4, 2004), 275);
              pop.add(new Day(10, 5, 2004), 325);
              pop.add(new Day(10, 6, 2004), 425);
              TimeSeriesCollection dataset = new TimeSeriesCollection();
              dataset.addSeries(pop);
              JFreeChart chart = ChartFactory.createTimeSeriesChart(
              "Population of CSC408 Town",
              "Date",
              "Population",
              dataset,
              true,
              true,
              false);
              try {
                ChartUtilities.saveChartAsJPEG(new File("C:\chart.jpg"),
                      chart, 500, 300);
              } catch (IOException e) {
                System.err.println("Problem occurred creating chart.");
              }
            }
}

 

 

Figura 4 - Un grafico per la rappresentazione dell'andamento di un valore (in ordinate) in un determinato periodo temporale (in ascisse).

Grafici "dashboard" o "cruscotto"

In anni recenti, grande rilevanza ha assunto il grafico "a cruscotto". Simile concettualmente al tachimetro di un'automobile, esso ha il pregio di rappresentare in maniera molto intuitiva dei valori, specie se si ha l'accortezza di colorare le varie "fasce di merito" con una codifica colore immediatamente intelligibile: il classico rosso, giallo e verde di semaforica provenienza è in grado di indicare immediatamente all'utente se il valore mostrato è negativo, accettabile o ampiamente positivo.

Cruscotto con JFreeChart

Vediamo un esempio semplice ma efficace: il grafico delle vendite di una società. Tenendo fuori tutti gli altri fattori, immaginiamo che a un certo livello di vendite corrisponda direttamente l'andamento dei conti della società [2]. Nel codice che segue si suppongono i seguenti valori:

  • 0-6500: la società è in perdita;
  • 6501-7000 : la società è in pareggio;
  • 7001-10000: la società è in attivo.

Vediamo l'esempio:

public class AchievementChartWithMeterChart extends ApplicationFrame {
            public AchievementChartWithMeterChart(String s) {
              super(s);
              JPanel panel = createPanel();
              panel.setPreferredSize(new Dimension(500, 350));
              setContentPane(panel);
            }
            private static JFreeChart createChart(ValueDataset valuedataset) {
              MeterPlot meterplot = new MeterPlot(valuedataset);
              //Imposto il valore minimo emassimo del range
              meterplot.setRange(new Range(0.0D, 10000D));
              //Valori di perdita 0 - 6500
              meterplot.addInterval(new MeterInterval("Loss", new Range(0.0D, 6500D), 
                  Color.red, new BasicStroke(2.0F), new Color(255, 0, 0, 128)));
              //Valore di pareggio 6500 - 7000
              meterplot.addInterval(new MeterInterval("break even", 
                      new Range(6501D, 7000D), 
                  Color.yellow, new BasicStroke(2.0F), new Color(255, 255, 0, 64)));
              //Valore di Guadagno 7000 - 10000
              meterplot.addInterval(new MeterInterval("Profit", 
                      new Range(7001D, 10000D),
                      Color.green, new BasicStroke(2.0F), 
                      new Color(0, 255, 0, 64)));
              meterplot.setNeedlePaint(Color.darkGray);
              meterplot.setDialBackgroundPaint(Color.white);
              meterplot.setDialOutlinePaint(Color.black);
              meterplot.setDialShape(DialShape.CHORD);
              meterplot.setMeterAngle(180);
              meterplot.setTickLabelsVisible(true);
              meterplot.setTickLabelFont(new Font("Arial", 1, 12));
              meterplot.setTickLabelPaint(Color.black);
              meterplot.setTickSize(5D);
              meterplot.setTickPaint(Color.gray);
              meterplot.setValuePaint(Color.black);
              meterplot.setValueFont(new Font("Arial", 1, 14));
              JFreeChart jfreechart = new JFreeChart("Sales Chart",
                      JFreeChart.DEFAULT_TITLE_FONT, meterplot, true);
              return jfreechart;
            }
            public static JPanel createPanel() {
              //Imposto come valore scelto 7500
              dataset = new DefaultValueDataset(7500D);
              JFreeChart chart = createChart(dataset);
              ChartPanel chartpanel = new ChartPanel(chart);
              return chartpanel;
            }
            public static void main(String args[]) {
              AchievementChartWithMeterChart meterChart 
                        = new AchievementChartWithMeterChart(
                          "Meter Chart Example");
              meterChart.pack();
              RefineryUtilities.centerFrameOnScreen(meterChart);
              meterChart.setVisible(true);
            }
            private static DefaultValueDataset dataset;
}

 

 

Figura 5 - Il grafico "cruscotto" è molto immediato e semplice da comprendere. Proprio per tale motivo, in anni passati ha avuto un successo così grande da essere impiegato spesso a sproposito, in situazioni in cui non si prestava bene a illustrare l'informazione del tipo di dato sottostante.

 

Conclusioni

Una libreria come JFreeChart ha avuto numerosi utilizzi e può tornare utile in molte occasioni, quando si voglia, per una qualunque ragione, mantenere un approccio "pure Java". Gli esempi presentati sono solo un esempio delle varie possibilità.

 

 

Riferimenti

[1] Il sito della libreria JFreeChart

http://www.jfree.org/jfreechart/

 

[2] Sales chart with meter chart

http://www.ayukucode.org/sales-chart-with-meter-chart/

Condividi

Pubblicato nel numero
204 marzo 2015
Yuri Cervoni si è laureato alla facoltà di Ingegneria Informatica dell’Università “La Sapienza” di Roma nel maggio 2009 con la tesi: “Implementazione e realizzazione di un metodo per l’animazione dell’algoritmo di Dijkstra”. Dall’Aprile 2009, prima come stagista e poi come sviluppatore software, lavora nella Società degli Studi di Settore. Nel…
Articoli nella stessa serie
Ti potrebbe interessare anche