Grafici in JavaME con MEChart
In questo articolo vediamo come generare grafici per la piattaforma JavaME utilizzando la libreria opensource MEChart
Introduzione
L’API MECHART è stata creata al fine di colmare un vuoto nella programmazione Java ME, la mancanza di una API con la quale costruire la grafica in maniera rapida e semplice, senza la necessità di programmare direttamente con la classe Canvas. Sviluppando sulla piattaforma Java SE abbiamo l’esempio del framework JFreeChart. Inoltre, c’è una crescente preoccupazione per l’interfaccia grafica delle nostre applicazioni, dovuta al progresso dei telefoni cellulari e anche alla facilità di creazione di interfacce in altri linguaggi e / o framework di programmazione per i dispositivi mobili.
Nella prima versione delle API MECHART era stato possibile creare tre tipi di grafici: linea, torta e barre. Nella seconda versione è stato aggiunto un nuovo tipo di grafico, il grafico combinato, che combina barre e linee. Inoltre, in questa nuova versione, è possibile creare grafici utilizzando colori RGB e non essere costretti ad utilizzare il set di colori predefiniti nelle API. Inoltre, è presente un metodo createImage per tutti i tipi di grafica, che restituisce un oggetto Image utilizzabile su una Canvas. Infine è stato aggiunta a questa ultima versione di MECHART anche la possibilità di creare grafici su Canvas, non solo come CustomItem.
Questo articolo mira a fornire una panoramica di come aggiungere MECHART al vostro progetto e a fare una sintesi dei metodi necessari per la creazione di quattro tipi di grafici disponibili. Infine, c’è l’invito a un maggior numero di persone che possano contribuire alla crescita di questa API.
MECHART: Il Progetto
MECHART è registrato come un progetto su java.net, disponibile all’indirizzo https://mechart.dev.java.net/. A questo indirizzo potete trovare i jar che necessari per la vostra applicazione, la documentazione e il codice sorgente. E’ importante notare che l’API sono rilasciate sotto licenza GPL, sono quindi benvenuti i contributi per la sua crescita. L’API è ancora in fase iniziale, gestita da due soli sviluppatori.
Attualmente, è possibile creare quattro tipi di grafici: grafico combinato (Figura 1), il grafico a barre (Figura 2), grafico a linee(Figura 3) e grafico a torta (Figura 4). La Figura 1 mostra un grafico ereditato dalla versione 1.0 delle API, che è costruito attraverso un’istanza della classe CustomItem. Il grafico a barre, illustrato nella figura 2, rappresenta un esempio della stessa classe. La figura 3 mostra un grafico a linee, che usa una delle nuove funzionalità di API MECHART, la costruzione di grafici attraverso un’istanza della classe Canvas. Infine, la figura 4 mostra l’uso del metodo createImage, che restituisce un’istanza della classe Image che può essere utilizzata sia in una Canvas che in una Form.
Utilizzare l’API con NetBeans
L’uso di un particolare IDE è a discrezione del lettore, tuttavia, non sarebbe possibile qui spiegare la configurazione di tutti gli IDE, quindi, è stato scelto NetBeans, che è molto popolare tra i programmatori Java. Utilizzando NetBeans 5.0 (o versioni successive) il lettore avrà una maggiore facilità, in quanto il WTK può essere collegato direttamente all’IDE. Si presume che il NetBeans Mobility Pack sia già installato, e che il WTK con cui si vuole sviluppare sia configurato, in quanto questo non è il focus di questo articolo. Dopo aver creato un nuovo progetto Mobile, il lettore deve accedere alle proprietà di esso, una schermata simile alla figura seguente
Si noti che sulla sinistra è selezionato “Libraries & Resources” , e sulla destra c’è il path del jar di mechart.
Utilizzare MECHART
Per continuare, è essenziale che il lettore abbia una conoscenza di base di Java ME. Il seguente codice mostra l’ossatura di base della nostra MIDlet senza l’uso di mechart.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import java.util.Vector; import javax.microedition.midlet.*; import javax.microedition.lcdui.*; import com.mechart.chart.*; public class Midlet extends MIDlet { private Display display; private Form fmMain; public void startApp() { display = Display.getDisplay(this); fmMain = new Form("Teste CustomItem"); display.setCurrent(fmMain); } public void pauseApp() { } public void destroyApp(boolean unconditional) { } } |
Per utilizzare uno dei quattro elementi grafici dobbiamo fare il seguente import
1 |
import com.mechart.chart.*; |
LineChart
Dopo aver definito l’oggetto LineChart, è necessario inizializzarlo e quindi aggiungerlo al Form. Il costruttore della classe LineChart riceve in totale nove parametri, che sono:
- Larghezza
- Altezza
- I dati del grafico
- La legenda
- L’identificazione dei dati
- La dimensione del font
- Il colore delle linee
- Il colore della parte inferiore del grafico
- Il valore massimo per il grafico
Per il colore, la LineChart ha già definito alcuni valori costanti da utilizzare, senza la necessità di conoscere i codici RGB dei colori. Ma per alcuni casi specifici, i colori dovrebbero essere definiti con i codici RGB. Ad esempio, quando lo sviluppatore riceve una bozza del layout grafico dell’applicazione, con usa colori che non esistono tra quelli predefiniti in LineChart, c’è bisogno di sapere il codice RGB per specificare il giusto colore. Il codice della seguente Midlet è relativo al grafico che possiamo vedere nell’immagine successiva (grafico a sinistra).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
import com.mechart.chart.LineChart; import java.util.Vector; import javax.microedition.midlet.*; import javax.microedition.lcdui.*; public class UsoLineChart extends MIDlet { private Display display; private Form fmMain; private LineChart lineChart; public void startApp() { display = Display.getDisplay(this); fmMain = new Form(""); ClCanvas cv = new ClCanvas(); fmMain.append(new StringItem("Balancete 1º Semestre", null)); short[][] posicoes = new short[][]{{50, 43, 19, 47, 90, 63}, {30, 13, 15, 82, 79, 50}, {23, 24, 49, 51, 70, 81}}; String[] legenda = new String[]{"Jan", "Fev", "Mar", "Abr", "Mai", "Jun"}; byte[] cores = new byte[]{LineChart.MAROON, LineChart.BLUE, LineChart.WHITE}; lineChart = new LineChart(cv.getWidth(), 75, posicoes, legenda, new String[] {"Produção", "Vendas", "Gastos"}, 1, cores, LineChart.GRAY, (short) 90); fmMain.append(lineChart); display.setCurrent(fmMain); } public void pauseApp() { } public void destroyApp(boolean unconditional) { } } class ClCanvas extends Canvas { protected void paint(Graphics graphics) { } } |
Il codice seguente invece illustra soltanto la creazione di un oggetto LineChart con codici RGB e il suo risultato è visibile nel grafico della precedente immagine (grafico a destra)
1 2 3 4 5 6 |
int[][] coresMat = new int[][]{new int[]{255, 0, 0}, new int[]{0, 255, 0}, new int[]{0, 0, 255}}; lineChart = new LineChart(cv.getWidth(), 75, posicoes, legenda, new String[]{"Produção", "Vendas", " Estoque"}, 1, coresMat, new int[]{220, 220, 220}, (short)90); |
Si noti che è stata creata anche una inner class che estende Canvas, per recuperare la larghezza e l’altezza del display del dispositivo. Se il progetto è indirizzato ad una piattaforma target e le sue dimensioni sono note, l’uso di questa Canvas non è necessario. Questa nuova versione delle API MECHART introduce alcuni miglioramenti che vengono riportati qui di seguito:
- Possibilità di creare il grafico con colori RGB
- Grafico a più linee
- Creazione del grafico con Canvas
- Possibilità di creare un Image di un grafico
I primi due punti sono stati mostrati prima. Per creare un grafico a linee, utilizzando una Canvas e non un CustomItem, c’è la classe LineChartCanvas. Il suo utilizzo è mostrato nel seguente codice, dove potete notare che solo il metodo startApp() è stato cambiato, non è più presente l’uso di Form. Inoltre, il costruttore della classe LineChartCanvas ha undici parametri e non nove come LineChart, di cui solo gli ultimi due differiscono: un byte che rappresenta la posizione, un vettore di interi che formano il codice RGB del colore di sfondo della Canvas non del grafico.
Il parametro di posizionamento può essere uno delle due costanti presenti nella classe: FULL e NONE. Utilizzando la costante NONE il grafico avrà come altezza quella definita nel costruttore, altrimenti, l’altezza del grafico sarà l’altezza del display del telefono, utile nei casi in cui lo sviluppatore vuole che il grafico venga visualizzato sullo schermo del telefono cellulare. La seguente immagine mostra il risultato del seguente codice, a sinistra utilizzando LineChartCanvas.FULL e a destra utilizzando LineChartCanvas.NONE.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
display = Display.getDisplay(this); short[][] posicoes = new short[][]{{50, 43, 19, 47, 90, 63}, {30, 13, 15, 82, 79, 50}, {23, 24, 49, 51, 70, 81}}; String[] legenda = new String[]{"Jan", "Fev", "Mar", "Abr", "Mai", "Jun"}; byte[] cores = new byte[]{LineChart.MAROON, LineChart.BLUE, LineChart.WHITE}; int[][] coresMat = new int[][]{ new int[]{255, 0, 0}, new int[]{0, 255, 0}, new int[]{0, 0, 255}}; display.setCurrent(new LineChartCanvas(cv.getWidth(), 100, posicoes, legenda, new String[]{"Produção", "Vendas", "Gastos"}, 1, cores, LineChart.GRAY, (short)90, LineChartCanvas.FULL, new int[]{20, 200, 200})); |
Come spiegato precedentemente,è possibile anche creare il grafico passando codici RGB. Lo stesso grafico che vediamo nell’immagine precedente può essere creato con il codice che viene riportato di seguito. Le modifiche riguardano soltanto il settimo e l’ottavo parametro, l’array di byte è sostituito da una matrice di numeri interi, e una costante di LineChartCanvas è sostituita da un vettore di interi.
1 2 3 4 5 6 |
display.setCurrent(new LineChartCanvas(cv.getWidth(), 100, posicoes, legenda, new String[]{"Produção", "Vendas", "Gastos"}, 1, coresMat, new int[]{180, 180, 180}, (short)90, LineChartCanvas.FULL, new int[]{200, 200, 200})); |
Inoltre, l’utente può creare un oggetto Image utilizzando il createImage di LineChartCanvas. Il seguente codice presenta la prima parte, il metodo startApp e, nel secondo, il codice della classe Canvas. I parametri passati sono necessari al metodo createImage per istanziare un oggetto della classe LineChartCanvas. Il risultato del codice è mostrato nella successiva immagine
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
public void startApp() { display = Display.getDisplay(this); ClCanvas cv = new ClCanvas(); display.setCurrent(cv); } ... ... ... class ClCanvas extends Canvas { Image img = null; Font fonte = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_MEDIUM); short[][] posicoes = new short[][]{{50, 43, 19, 47, 32, 90}, {30, 13, 15, 82, 79, 50}, {23, 24, 49, 51, 70, 81}}; String[] legenda = new String[]{"Jan", "Fev", "Mar", "Abr", "Mai", "Jun"}; int[][] coresMat = new int[][]{new int[]{255, 0, 0}, new int[]{0, 255, 0}, new int[]{0, 0, 255}}; public ClCanvas() { img = LineChartCanvas.createImage(getWidth(), 100, posicoes, legenda, new String[]{"Produção", "Vendas", "Gastos"}, 1, coresMat, new int[]{255, 255, 255}, (short) 90, LineChartCanvas.NONE, new int[]{200, 200, 200}); setFullScreenMode(true); } protected void paint(Graphics g) { g.setColor(220, 220, 220); g.fillRect(0, 0, getWidth(), getHeight()); g.setFont(fonte); g.setColor(0, 0, 0); g.drawString("Teste da MECHART", getWidth() / 2, 0, Graphics.HCENTER | Graphics.TOP); g.drawString("Dados empresariais", getWidth() / 2, fonte.getHeight(), Graphics.HCENTER | Graphics.TOP); g.drawImage(img, 0, fonte.getHeight() * 2, Graphics.LEFT | Graphics.TOP); g.setColor(255, 0, 0); g.drawLine(0, fonte.getHeight() * 2, getWidth(), fonte.getHeight() * 2); } } |
PieChart
Il grafico a torta, forse il più conosciuto, viene creato con la classe PieChart. Il costruttore riceve cinque parametri che sono:
- Larghezza
- Altezza totale del grafico
- I dati
- Grandezza del font
- Colori definiti per le diverse sezioni
L’ultimo parametro è passato in un array di byte. I byte che definiscono i colori principali sono disponibili come costanti stitiche nella classe PieChart. Il seguente esempio mostra l’uso di PieChart.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
import com.mechart.chart.PieChart; import java.util.Vector; import javax.microedition.midlet.*; import javax.microedition.lcdui.*; public class UsoPieChart extends MIDlet { private PieChart pieChart; private Form fmMain; private Display display; public void startApp() { display = Display.getDisplay(this); Vector dados = new Vector(); dados.addElement(new String[]{"Brasil", "50"}); dados.addElement(new String[]{"Alemanha", "88"}); dados.addElement(new String[]{"Itália", "71"}); dados.addElement(new String[]{"Argentina", "45"}); dados.addElement(new String[]{"Uruguai", "22"}); Canvas cv = new Canvas() { protected void paint(Graphics graphics) { } }; fmMain = new Form(""); fmMain.append(new StringItem("Gráfico: ", "Participacao PIB")); pieChart = new PieChart(cv.getWidth(), 70, dados, 1, new byte[]{PieChart.BLACK, PieChart.BLUE, PieChart.GREEN, PieChart.WHITE, PieChart.RED}); fmMain.append(pieChart); display.setCurrent(fmMain); } public void pauseApp() { } public void destroyApp(boolean unconditional) { } } |
La creazione del grafico a torta ha due punti cruciali, una istanza della classe Vector che comunica i dati e il vettore di byte relativi ai colori di ogni sezione. L’immagine successiva mostra il risultato del precedente esempio.
Inoltre, è possibile passare come parametro un array di interi con i codici RGB invece di un array di byte. Per vedere come fare ciò potete vedere il codice seguente.
1 2 3 4 5 6 7 8 |
pieChart = new PieChart(cv.getWidth(), 70, dados, 1, new int[][]{ new int[]{0, 0, 0}, new int[]{0, 0, 255}, new int[]{0, 255, 0}, new int[]{255, 255, 255}, new int[]{255, 0, 0}}); fmMain.append(pieChart); |
Come il LineChart, anche il PieChart ha avuto dei miglioramenti in questa versione più recente di MECHART. Per creare grafici come istanza di Canvas è possibile utilizzare la classe PieChartCanvas. Il seguente esempio mostra il codice necessario per creare un grafico tramite PieChartCanvas.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
display = Display.getDisplay(this); Vector dados = new Vector(); dados.addElement(new String[]{"Brasil", "50"}); dados.addElement(new String[]{"Alemanha", "88"}); dados.addElement(new String[]{"Itália", "71"}); dados.addElement(new String[]{"Argentina", "45"}); dados.addElement(new String[]{"Uruguai", "22"}); Canvas cv = new Canvas() { protected void paint(Graphics graphics) {} }; int[][] coresMat = new int[][]{new int[]{0, 0, 0}, new int[]{0, 0, 255}, new int[]{0, 255, 0}, new int[]{255, 255, 255}, new int[]{255, 0, 0}}; display.setCurrent(new PieChartCanvas(cv.getWidth(), 100, dados, 1, new byte[]{PieChartCanvas.BLACK, PieChartCanvas.BLUE, PieChartCanvas.GREEN, PieChartCanvas.WHITE,PieChartCanvas.RED}, PieChartCanvas.FULL,new int[]{200, 200, 200})); |
E ‘importante sottolineare due punti, in primo luogo, i cambiamenti si verificano solo nel metodo startApp, e in secondo luogo solo due parametri sono stati aggiunti a quelli già utilizzati in precedenza. Un byte che identifica la posizione del grafico, FULL o NONE (come in LineChartCanvas), e un array di interi che rappresentano il colore di sfondo della Canvas. Il seguente esempio mostra l’uso della classe con valori RGB e l’immagine successiva ci permette di vedere il risultato di questo codice.
1 2 3 4 5 6 7 8 |
int[][] coresMat = new int[][]{ new int[]{0, 0, 0}, new int[]{0, 0, 255}, new int[]{0, 255, 0}, new int[]{255, 255, 255}, new int[]{255, 0, 0}}; display.setCurrent(new PieChartCanvas(cv.getWidth(), 100, dados, 1, coresMat,PieChartCanvas.FULL, new int[]{200, 200, 200})); |
Il metodo createImage della classe PieChartCanvas riceve gli stessi parametri del costruttore PieChart. Il suo utilizzo è uguale a quello visto in LineChartCanvas. Il seguente esempio di codice mostra l’uso di questo metodo in due modi, in primo luogo, utilizzando i codici RGB e, nel secondo, utilizzando le costanti pre-definite nella classe. L’immagine successiva mostra il risultato dei due esempi.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
img = PieChartCanvas.createImage(getWidth(), 100, dados, 1, new int[][]{new int[]{0, 0, 0}, new int[]{255, 255, 255}, new int[]{0, 255, 0}, new int[]{255, 0, 0}, new int[]{100, 100, 100}}, PieChartCanvas.NONE, new int[]{200, 200, 200}); ... ... ... img = PieChartCanvas.createImage(getWidth(), 100, dados123, 1, new byte[]{PieChartCanvas.WHITE, ...}, PieChartCanvas.NONE, new int[]{200, 200, 200}); |
BarChart
Il grafico a barre è costruito con l’uso della classe BarChart di mechart, il suo costruttore è simile ad altre API grafiche. I parametri passati sono:
- Larghezza
- Altezza totale del grafico
- I dati (un vettore dove ogni vettore è una delle componenti del grafico)
- Il vettore di byte che rappresenta i colori utilizzati
- Un byte che rappresenta il colore di sfondo del grafico
- Il valore massimo che il grafico riceverà
Come le altre classi delle API, il BarChart ha alcuni valori statici e costanti utilizzati per definire i principali colori. L’utilizzo di questa classe è simile alle precedenti, infatti è presente come negli altri casi una classe (BarChartCanvas) che ci permette di gestire il grafico all’interno di un Canvas. L’unica differenza sostanziale riguarda il metodo fullChart() di BarChart. Utilizzando questo metodo possiamo dire a MECHART se vogliamo che il grafico con le sue linee occupi tutto lo spazio in orizzontale o meno.
Riferimenti
Articolo originale – Gráficos em Java ME com MECHART 2.0
Gráficos em Java ME com MECHART 1.0
Il progetto su Java.net
http://www.mobilidadetudo.com/