MokaByte Numero  38  - Febbraio  2000
Le Swing in pratica
III parte: i Layout manager
di
Daniela Micucci
Aggiunta e posizionamento di Component su Container...
in poche parole i Layout Manager

Come realizzare interfacce grafiche belle ed accattivanti? La risposta è: avere un po' di gusto (!!!) e conoscere la modalità con cui le classi Java gestiscono le componenti all'interno dei container. In questo articolo si cominceranno ad analizzare i cosiddetti layout manager..

Introduzione
Qualsiasi componente grafico si voglia visualizzare (da un bottone fino ad una label con immagine), deve essere inserito (aggiunto) all'interno di un contenitore. Non può esistere un componente, per così dire, "isolato". 
Una volta inseriti i componenti all'interno di un contenitore, il layout manager associato al contenitore provvede a determinare la dimensione e la posizione dei componenti all'interno del contenitore stesso secondo le proprie regole. Il contenitore delega quindi al proprio layout manager il compito di posizionare e dimensionare i propri componenti. Se ci limitiamo a creare una finestra e ad aggiungervi un'area di testo, accontentandoci del risultato mostrato nella Figura 1, non dobbiamo neanche preoccuparci dell'esistenza dei layout manager.

Figura 1 - JFrame con LayoutManager di default

Ma se dobbiamo costruire interfacce utente un po' più complesse come quella riportata nella Figura 2, allora dobbiamo familiarizzare con i layout manager che Java ci mette a disposizione. 

Figura 2 - Un'interfaccia grafica un po' più complessa

Prima di addentrarci ad analizzare come si comportano i vari layout manager, occorre soffermarci sulla modalità di inserimento di un componente all'interno del proprio contenitore. La classe Container, supercalsse di tutti i contenitori, pubblica un metodo chiamato add per adempiere a questo compito. La sintassi completa è: add(Component)
Per esempio: l'aggiunta di un bottone - button, ad un pannello - panel -, si otterrà scrivendo: panel.add(button)
Il metodo add è overlodato, tanto che nella versione corrente (1.2.2) ne esistono ben 5 varianti. È il layout manager associato al container che ci obbliga ad usare una versione piuttosto che un'altra. Se si considera, ad esempio, il layout manager BorderLayout, occorre specificare, oltre la componente da aggiungere, anche la posizione all'interno del contenitore stesso. Generalmente, la maggior parte dei layout manager posizionano le componenti basandosi unicamente sull'ordine con cui queste sono aggiunte al contenitore. 
Infine, se il layout manager di un Container non soddisfa le nostre esigenze è sempre possibile cambiarlo grazie al metodo setLayout(LayoutManager) che risiede, anch'esso, nella classe Container.
 
 
 

I LayoutManager in Java
Esistono ben 6 LayoutManager e precisamente FlowLayout, BorderLayout, GridLayout, BoxLayout (solo dalla versione 1.2), CardLayout e GridBagLayout. Cominiamo ad analizzare in questo articolo i primi due. Negli articoli che seguiranno tratteremo i layout manager rimanenti e realizzeremo l'interfaccia utente riportata nella Figura 2.
 
 
 

FlowLayout
È il layout manager più semplice: si limita a posizionare le componenti su di una riga, una di seguito all'altra, nell'ordine in cui queste sono aggiunte al contenitore e dimensionate alla loro preferred size. Nelle figure Figura 2 e Figura 3 è mostrato un esempio in cui viene impostato come layout manager di un JFrame un FlowLayout. 

Figura 2 - JFrame con FlowLayout: le componenti sono posizionate su di un'unica riga

Se lo spazio orizzontale non è sufficiente a contenere in un'unica riga tutte le componenti, quelle "residue", le posiziona nella riga successiva.

Figura 3 - JFrame con FlowLayout: le componenti sono posizionate su più righe

Il sorgente che realizza parte dell'interfaccia grafica mostrata nelle figure è il seguente, tenuto conto che la classe contenete le istruzioni stesse è una specializzazione del JFrame:

getContentPane().setLayout(new FlowLayout());
getContentPane().add(new JButton("1"));
getContentPane().add(new JButton("due"));
getContentPane().add(new JLabel("Label"));
getContentPane().add(new JTextField("TextField"));
getContentPane().add(new JButton("Premi per uscire"));
getContentPane().add(new JComboBox());
Con l'istruzione setLayout(new FlowLayout()) è stato modificato il layout manager del JFrame e l'aggiunta delle componenti alla finestra è stata realizzata mediante l'utilizzo del metodo add. Entrambe le istruzioni sono state eseguite sul ContentPane del JFrame e non direttamente sul JFrame come accadeva con le AWT.
Come è possibile notare nelle figure Figura 2 e Figura 3 le componenti sono state allineate a partire dal centro delle righe e lo spazio tra le componenti risulta contenuto (5 pixel). È possibile modificare queste impostazioni utilizzando altri costruttori della classe FlowLayout, più precisamente:
public FlowLayout()
Allinea le componenti centralmente con spazio tra le stesse di 5 pixel sia in orizzontale che in verticale.
public FlowLayout(int allineamento)
Allinea le componenti sulla base del valore specificato come argomento. 
Tra gli allineamenti possibili: 
FlowLayout.CENTER, 
FlowLayout.LEFT,
FlowLayout.RIGHT.
Il numero di pixel tra una componete e l'altra è di 5 unità sia in orizzontale che in verticale.
 
public FlowLayout(int allineamento, int gapOrizzontale, int gapVerticale)
Allinea le componenti sulla base del valore specificato come argomento. 
Tra gli allineamenti possibili: 
FlowLayout.CENTER, 
FlowLayout.LEFT,
FlowLayout.RIGHT.
Il numero di pixel tra una componete e l'altra è specificato dai valori passati come argomento.
 
 
 

BorderLayout
Se un Container ha associato un BorderLayout, è possibile inserire solo fino a 5 componenti. Ciò è dovuto al fatto che un BorderLayout divide l'area del Container in 5 zone ben distinte: North, South, East, West e Center. Per poter inserire una componente è necessario, quindi, specificare in quale area posizionarla. Il metodo add che accetta in ingresso solo il component non va più bene, occorre usare, quindi, quello che specifica anche la posizione:

add(String zona, Componenet componente)
zona è una stringa che identifica l'area su cui deve essere posizionato il componente. I valori possibili sono: North, South, East, West e Center.
Dalla versione 1.2 di Java è stato introdotto anche il seguente:
add(Component componente, Object zona)
zona è un oggetto che identifica l'area su cui deve essere posizionato il componente. I valori possibili sono: BorderLayout.NORTH, BorderLayout.SOUTH, BorderLayout.EAST, BorderLayout.WEST e BorderLayout.CENTER.
Occorre ricordare che l'aggiunta di due o più componenti nella stessa zona fa si che venga visualizzata solo l'ultima aggiunta, le altre sono nascoste.
Se si utilizza il metodo add standard che accetta in ingresso solo la componente in un container a cui è associato un BorderLayout, tale componente è posizionata in centro: add(new Button("ok")) è equivalente a add("Center", new Button("ok")) e a add(new Button("ok"), BorderLayout.CENTER).
Un'altra forte differenza con il FlowLayout è che questo layout ignora la preferred size delle componenti, assegnando loro una dimensione che è determinata dallo spazio attualmente disponibile per la zona in cui sono localizzate. L'esempio riportato in Figura 4 mostra questa proprietà.

Figura 4 - JFrame con BorderLayout e componenti in ogni zona

Se la finestra viene ridimensionata, le componenti vengono anch'esse ridimensionati in modo tale da adattarsi al nuovo spazio disponibile. La zona centrale, infine, è quella privilegiata: se alcune zone non contengono componenti, quella centrale le va ad occupare con la sua componente come mostrato in Figura 5 in cui esiste solo un'area di testo al centro e un bottone a sud.

Figura 5 - JFrame con BorderLayout e componenti solo a nord ein centro

Come per il FlowLayout, anche per il BorderLayout è possibile specificare lo spazio in pixel da lasciare tra una componente e quella adiacente. è possibile fare ciò scegliendo tra i due costruttori, quello che più si avvicina alle nostre esigenze:

public BorderLayout()
Il numero di pixel tra una componete e l'altra è di 5 unità sia in orizzontale che in verticale.
public BorderLayout( int gapOrizzontale, int gapVerticale)
Il numero di pixel tra una componete e l'altra è specificato dai valori passati come argomento.
Per questo articolo ci fermiamo qui, nel prossimo proporremo altri 3 layout manager, mentre gli ultimi e la realizzazione dell'interfaccia proposta in Figura 2 saranno argomento di un successivo articolo.
Chi volesse mettersi in contatto con la redazione può farlo scrivendo a mokainfo@mokabyte.it