martedì 22 giugno 2010

Java: gestione dei layout per le GUI

Le GUI, graphical user interface, svolgono l'importante compito dell'interfacciamento fra programma e utente. Java offre al programmatore, e indirettamente all'utente, numerosi componenti per l'interfaccia grafica. La libreria di riferimento è ancora una volta la libreria Swing di Java. Attraverso questa si possono istanziare bottoni, aree di testo, campi di testo per password, menu etc... Ancora prima di vedere come ciò può essere fatto dobbiamo necessariamente preoccuparci di un'importante questione, la gestione del layout.
Come andranno posizionati all'interno del frame i componenti dell'interfaccia Swing? Di default, Java utilizza un layout non sempre idoneo all'applicazione che abbiamo in mente. Questo, infatti, inserisce ogni componente al centro del frame, a partire dalla prima riga utile nel frame. Quando lo spazio per un nuovo componente non è sufficiente a contenere lo stesso sulla medesima riga, quest'utlimo viene dunque inserito su una riga a parte!



JButton buttonA=new JButton("A");
JButton buttonA=new JButton("B");
JButton buttonA=new JButton("C");
JButton buttonA=new JButton("D");
JButton buttonA=new JButton("E");
JButton buttonA=new JButton("F");
add(buttonA);
add(buttonB);
add(buttonC);
add(buttonD);
add(buttonE);
add(buttonF);

Il gestore di layout di flusso, quello usato di default da Java, permette l'allineamento dei componenti a destra o a sinistra del frame. La scelta può essere fatta invocando il metodo setLayout nel costruttore del pannello e passando allo stesso una delle due costanti FlowLayout.LEFT oppure FlowLayout.RIGHT. Ecco un esempio:

setLayout(new FlowLayout(FlowLayout.LEFT));

Esiste anche un costruttore per layout di flusso che permette di specificare oltre all'allineamento anche le distanze orizzontali e verticali fra i componenti dell'interfaccia. Per ulteriori informazioni consultate la documentazione in linea. Come dicevo poco fa non sempre questo layout può andare bene per la GUI che abbiamo in mente. Esiste allora un diverso gestore di layout, ossia il gestore di layout di bordi. Quest'ultimo, suddividendo il frame in più aree, permette l'aggiunta dei componenti in ognuna di esse.


this.setLayout(new BorderLayout());
JButton northButton=new JButton("Nord");
JButton westButton=new JButton("Ovest");
JButton centerButton=new JButton("Centro");
JButton centerButtonFlip=new JButton("Inverti");
JButton eastButton=new JButton("Est");
JButton southButton=new JButton("Sud");
add(northButton,BorderLayout.NORTH);
add(westButton,BorderLayout.WEST);
add(centerButtonFlip,BorderLayout.CENTER);
add(centerButton,BorderLayout.CENTER);
add(eastButton,BorderLayout.EAST);
add(southButton,BorderLayout.SOUTH);


L'immagine dovrebbe mostrare alcune importanti limitazioni di questo layout. La prima cosa che salta subito agli occhi è che i componenti vengono sì aggiunti nelle rispettive aree del frame ma vanno, purtroppo, ad occupare l'intero spazio! Ed ancora, osservando attentamente il codice scoprirete che all'interno di esso erano stati chiesti 2 bottoni al centro, nel frame ne appare uno solo! Questo perchè ogni componente aggiunto in una zona del frame sovrasta, se presente, un componente aggiunto in precedenza. Il problema può essere tranquillamente aggirato assegnando il componente in un pannello a parte e aggiungendo, quindi, lo stesso pannello al pannello con il layout!

this.setLayout(new BorderLayout());
JPanel northPanel=new JPanel();
JButton northButton=new JButton("Nord");
northPanel.add(northButton);
this.add(northPanel,BorderLayout.NORTH);
JPanel westPanel=new JPanel();
JButton westButton=new JButton("Ovest");
westPanel.add(westButton);
this.add(westPanel,BorderLayout.WEST);
JPanel centerPanel=new JPanel();
JButton centerButton=new JButton("Centro");
JButton centerButtonFlip=new JButton("Inverti");
centerPanel.add(centerButton);
centerPanel.add(centerButtonFlip);
this.add(centerPanel,BorderLayout.CENTER);
JPanel eastPanel=new JPanel();
JButton eastButton=new JButton("Est");
eastPanel.add(eastButton);
this.add(eastPanel,BorderLayout.EAST);
JPanel southPanel=new JPanel();
JButton southButton=new JButton("Sud");
southPanel.add(southButton);
this.add(southPanel,BorderLayout.SOUTH);


Direi che va decisamente meglio. Nell'esempio mostrato sopra ho quindi creato un pannello per ogni area o bordo. Ho poi aggiunto i componenti dell'interfaccia in questi pannelli e infine ho aggiunto gli stessi al frame, collocandoli nelle rispettive aree. Ciò funziona perchè di default, per un pannello, il gestore di layout è un gestore di layout di flusso! L'ultimo gestore di layout che vi presento permette di disporre i componenti dell'interfaccia utente secondo una griglia:

setLayout(new GridLayout(4,4,5,5));
JButton button1=new JButton("1");
JButton button2=new JButton("2");
JButton button3=new JButton("3");
JButton button4=new JButton("4");
JButton button5=new JButton("5");
JButton button6=new JButton("6");
JButton button7=new JButton("7");
JButton button8=new JButton("8");
JButton button9=new JButton("9");
JButton button0=new JButton("0");
JButton buttonSum=new JButton("+");
JButton buttonDiff=new JButton("-");
JButton buttonMul=new JButton("*");
JButton buttonDiv=new JButton("/");
JButton buttonCalc=new JButton("=");
JButton buttonCanc=new JButton("Canc");
add(button1);
add(button2);
add(button3);
add(buttonSum);
add(button4);
add(button5);
add(button6);
add(buttonDiff);
add(button7);
add(button8);
add(button9);
add(buttonMul);
add(buttonCanc);
add(button0);
add(buttonCalc);
add(buttonDiv);


L'ordine di aggiunta per i componenti ha dunque inizio a partire dalla prima cella in alto a sinistra. Il costruttore del layout permette di specificare il numero di righe e di colonne (i primi due parametri), se necessario è poi possibile indicare le distanze verticali e orizzontali, in pixel, che devono esistere fra i componenti (gli ultimi due parametri).

Nessun commento:

Posta un commento