Articoli Manifesto Tools Links Canali Libri Contatti ?
User Interface Design

Uso efficace dei Layout Managers

Abstract
Nella progettazione di una user interface ben fatta, con un qualunque toolkit non elementare, ha grande rilievo la conoscenza e l'uso in maniera adeguata dei layout managers. In quest'articolo l'interesse non sarà rivolto ad un solo toolkit in particolare. Gli esempi che verranno presentati saranno realizzati sia con le Swing (il toolkit di Java 2) che con il GTK+ (uno fra i più famosi disponibili per il linguaggio C).
Data di stesura: 23/11/2002
Data di pubblicazione: 29/11/2002
Ultima modifica: 04/04/2006
di Marco Lamberto Discuti sul forum   Stampa

Fixed Positioning, l'assenza di un layout manager

Partiamo dal posizionamento fisso, ovvero la mancanza di un layout manager. la disposizione dei componenti è determinata dalla posizione, in coordinate relative alla finestra contenitore di ogni singolo widget (window gadget), e dalle sue dimensioni.
Questo approccio comporta un layout bloccato e di difficile, o quanto meno scomoda, gestione in caso di eventi di ridimensionamento della finestra contenitrice.
Come possiamo vedere nella seguente illustrazione, un fixed positioning non reagisce molto bene al cambiamento di dimensioni della dialog, questa è un'operazione che arriva perfino a "mutilarne" il contenuto rendendo inaccessibili alcuni elementi.
[Figura 1]

Figura 1: Esempi di posizionamento fisso in caso di ridimensionamento della finestra. In rosso è evidenziata la dimensione (fissa) per cui è stata progettata la finestra.

La progettazione più semplice, o naturale, per un utente alle prime armi potrebbe sembrare quella a posizionamento fisso, poiché spesso, agli occhi dello sviluppatore inesperto, i layout manager appaiono come entità misteriose (forse perché sono - apparentemente - invisibili e complicati) che operano in maniera "contorta" e spesso "capricciosa": "il bottone non vuole stare giù!", "mi si allarga tutto!", "prima era li, ho spostato quello ed è cambiato tutto!", ...

Il posizionamento fisso però si trascina una serie di svantaggi che già in una UI (user interface) banale possono diventare critici. Primo fra tutti è la necessità di bloccare le dimensioni della finestra per evitare di incappare nelle problematiche sopra esposte. Ciò, in caso di risoluzioni video elevate, impedisce di usare tutto lo spazio disponibile sullo schermo. Il caso opposto è persino peggiore, quello cioè in cui le dimensioni dello schermo sono nettamente inferiori a quelle adottate dall'applicazione (non ridimensionabile).

Per evitare questi problemi si potrebbe ricorrere ad un ridimensionamento e riposizionamento "al volo" di alcuni componenti ogni qualvolta le dimensioni della finestra principale venissero alterate.

Ma il codice per fare questo è stato già scritto e possiamo usarlo tranquillamente coi layout managers!

I Layout Managers sono griglie ordinate

O meglio, i layout managers sono algoritmi di ordinamento che nelle versioni più comunemente utilizzate si occupano di distribuire dei widgets all'interno di griglie.

I layout managers hanno proprio il compito di gestire tutti i componenti che sono disposti sulla loro griglia in base anche a determinati suggerimenti che il programmatore può passare loro (constraints).

I layout managers sono dei componenti basilari di una user interface, sono fondamentalmente delle griglie con comportamenti predefiniti e più o meno alterabili.
È possibile farne una sommaria classificazione prendendo come esempi quelli disponibili in un paio di toolkits estremamente diffusi, le Swing di Java ed il GTK+, utilizzabile dal linguaggio C ma anche da molti altri (Perl, Python, ...).

Tipologia Layout Managers
Swing GTK+
Griglie con tutte le celle di uguali dimensioni GridLayout HorizontalButtonBox, VerticalButtonBox
Griglie con celle di differenti dimensioni BorderLayout, FlowLayout HorizontalBox, VerticalBox
Tabelle GridBagLayout Table
Un uso tipico della prima classe di layout managers è sicuramente quello di una barra di bottoni, permettendo di avere tutti gli elementi dimensionati in base a quello al più grande fra questi.
[Figura 2]

Figura 2: GridLayout

[Figura 3]

Figura 3: FlowLayout

Sicuramente i bottoni principali di una dialog in Java sono disposti in maniera ottimale usando un GridLayout, l'uso di un FlowLayout rischierebbe di creare dominanze fra i bottoni contenenti descrizioni più lunghe finendo per dare maggiore importanza visiva a operazioni che non necessariamente lo sono anche in pratica.
Nella seconda riga di bottoni l'"Ok" è decisamente più difficile da individuare e selezionare con il mouse degli altri in quanto occupa un'area inferiore (fino al 50% più piccolo degli altri tre).
FlowLayout Dispone i componenti lungo un flusso orizzontale (allineato a destra, sinistra o centrato). Le dimensioni dei componenti non vengono alterate, il layout manager si preoccupa di creare una nuova riga subito sotto nel caso in cui non fosse possibile allocare spazio per l'aggiunta di nuovi elementi alla propria sinistra.
GridLayout È una griglia con celle tutte uguali fra di loro. Larghezza ed altezza di ogni singola cella sono dipendenti dai componenti aventi maggiore larghezza o altezza. Gli altri componenti vengono allargati in modo da coprire tutto lo spazio della rispettiva cella.

Ovviamente nel caso di GTK+ cambiano i nomi ma la situazione è la stessa.

[Figura 4]

Figura 4: HorizontalButtonBox

[Figura 5]

Figura 5: HorizontalBox

Un esempio

Prenderemo ora in esame un paio di finestre d'esempio costruite con i toolkits citati cercando analogie e differenze di comportamento.
[Figura 6]

Figura 6

[Figura 7]

Figura 7

Le due finestre realizzate per quest'esempio sono molto simili, ma la gerarchia dei widgets è leggermente diversa:
[Figura 8]

Figura 8: GTK+

[Figura 9]

Figura 9: Swing

Una delle differenze più evidenti è il minor numero di componenti necessarie per realizzare la stessa UI in GTK+.
In GTK+ non esiste una separazione netta fra contenitore e layout manager come nelle Swing, bensì i layout managers (altresì noti come packers) sono dei contenitori a tutti gli effetti.
Questo tuttavia dipende dalle scelte effettuate durante la progettazione delle gerarchie di ereditarietà fra i vari widgets: nelle Swing i layout managers sono derivati immediatamente da java.lang.Object (non sono quindi componenti appartenenti agli elementi di UI pur manipolandoli), mentre in GTK+ sono estensioni di GtkContainer.
I packers di GTK+ possiedono generalmente molte più opzioni (constraints) per il layout di quante ne abbiano i layout "semplici" delle Swing (BorderLayout, FlowLayout, GridLayout) finendo per somigliare più a versioni ridotte del GridBagLayout.
Pro e contro per queste scelte ve ne sono per entrambi i toolkits, per esempio avere più opzioni per un layout manager permette di ridurre il numero di pannelli e layout managers accessori ma al contempo ne aumenta la complessità d'uso.

Pensare e dividere il layout in blocchi (pannelli)

Una user interface va vista a strati (come le cipolle e gli orchi) quelli più esterni conterranno gruppi di componenti e a loro volta ogni gruppo potrà contenerne altri.
[Figura 10]

Figura 10

Pensando la finestra o il pannello principale come la base di una pila di componenti, ogni livello inferiore conterrà l'opportuno layout manager per disporre quelli immediatamente superiori e solo quelli poiché sarà compito del livello superiore gestire quelli al livello a lui sovrastante, e così via fino ad arrivare ai widgets.
[Figura 11]

Figura 11: Buttonbar in GTK+

L'HorizontalButtonBox ci permette di inserire dei bottoni equispaziati ed equidimensionati, per allinearli a destra basta impostare il packing alla fine del container (il lato destro).
[Figura 12]

Figura 12: Buttonbar con le Swing

Nel caso di Java serve un po' più di perizia per evitare di dover scomodare il GridBagLayout. La button bar è realizzata con un pannello con un GridLayout per garantire i bottoni tutti uguali, il pannello è ospitato dentro un altro pannello ma con un FlowLayout allineato a destra.

Non bisogna aver paura di usare qualche pannello in più per disporre in maniera opportuna dei widgets. Bisogna fondamentalmente tener presente il comportamento dei singoli layout managers (non sono molti!), cercare quelli che meglio si adattano a determinate problematiche ed eventualmente combinarne più d'uno con sotto-pannelli ausiliari in modo da disporre le aree nel migliore dei modi.

Conclusioni

In questo primo articolo di User Interface Design ho voluto evidenziare quanto la conoscenza approfondita dei layout managers di un toolkit sia estremamente importante per realizzare UI complesse nel migliore dei modi.
Vorrei inoltre sottolineare che:
la progettazione visuale con un GUI builder deve essere il passo successivo ad una fase di analisi
Procedete quindi a realizzare la UI solo dopo aver steso almeno una bozza in cui delineate le aree ed i layout managers in gioco per ognuna.
Costruire da zero una UI con un GUI builder senza avere le idee chiare sin dall'inizio può solo portarvi, nel migliore dei casi, ad usare troppo frequentemente le funzionalità di taglia e incolla!

Alcune delle critiche più frequenti all'uso di molte componenti "cosmetiche" come pannelli e layout managers sono:

  • eccessiva complessità durante lo sviluppo e dell'insieme finale
  • spreco di memoria
La complessità è un fattore relativo, l'analisi preliminare servirà a chiarire eventuali dubbi nella lettura a posteriori del codice.
Lo spreco di memoria è irrisorio, layout managers e pannelli sono componenti "leggere", la memoria che viene realmente allocata per questi non è molta e comunque non va mai considerata sprecata se risulta da una progettazione ottimale e ben strutturata.

"Divide et impera" è molto spesso il modus operandi ottimale per la soluzione di molti problemi complessi, non solo di UI.

Informazioni sull'autore

Marco Lamberto, laureato in Informatica presso la Statale di Milano, con diversi anni di esperienza sistemistica, di sicurezza e sviluppo prevalentemente in ambienti UNIX (Linux in primis) con linguaggi come C, Java, Perl, PHP, XML, HTML, ...

È possibile consultare l'elenco degli articoli scritti da Marco Lamberto.

Altri articoli sul tema User Interface Design.

Risorse

  1. I sorgenti dell'esempio in C per il toolkit GTK+.
    http://www.siforge.org/articles/2002/11/layout-managers/gtkLayoutManagerEx1.zip (164Kb)
  2. I sorgenti dell'esempio in Java sul toolkit Swing.
    http://www.siforge.org/articles/2002/11/layout-managers/swingLayoutManagerEx1.zip (14Kb)
  3. Home page del progetto GTK+.
    http://www.gtk.org/
  4. Home page del progetto GNOME.
    http://www.gnome.org/
  5. Sito ufficiale di Glade, il GTK+/GNOME gui builder.
    http://glade.gnome.org/
  6. Sezione del Java Tutorial di Sun relativa alla creazione di interfacce utente con le Swing.
    http://java.sun.com/docs/books/tutorial/uiswing/
  7. Java Foundation Classes (JFC) home page.
    http://java.sun.com/products/jfc/
Discuti sul forum   Stampa

Cosa ne pensi di questo articolo?

Discussioni

Questo articolo o l'argomento ti ha interessato? Parliamone.