ePrometeusCorsoJavaJava
testi articoli
Testi Articoli  Download
Home | Eshop | Java | Tools | Web | 
CorsoJava è ora Video! Free for all!
Clicca Qui!

JBUILDER JDBCL
Applicazioni data-oriented con Borland JBuilder e JBCL
Caratteristiche della JBCL
GUI con JBuilder
Dataset e Columns
Risoluzione delle query

<<< GUI con JBuilder >>>

I programmi in Java devono essere indipendenti dalla risoluzione. Questo requisito, che è del tutto naturale per un linguaggio multipiattaforma, ha un impatto sul modo in cui sono scritti i programmi che utilizzano interfacce grafiche. La libreria AWT ha introdotto la gestione geometrica delle GUI: invece di disporre i componenti sulle form posizionandoli per coordinate, si utilizzano i cosiddetti LayoutManager, che posizionano i componenti dentro una form contenitore, e consentono di ottenere interfacce grafiche ridimensionabili, che si autoadattano alla dimensione del contenitore. Purtroppo gli ambienti Java della prima generazione erano spesso un adattamento di ambienti C++ per Windows, con editor visuali che generalmente non permettevano di sfruttare visualmente i LayoutManager ma solo di posizionare i componenti per coordinate. Per sviluppare codice indipendente dalla risoluzione occorreva allora scrivere manualmente il codice che descriveva l’interfaccia. JBuilder per fortuna di utilizzare la gestione geometrica delle interfaccie, anche se prevede un layout manager, l’XyLayout, che posiziona i componenti in un contenitore per coordinate.

Facciamo dunque un breve riepilogo della gestione geometrica. Il modello della AWT suddivide gli elementi di interfaccia grafica in Component (come i Button, i TexField eccetera) e Container; questi ultimi possono essere finestre indipendenti (Frame, Window, Dialog) oppure incorporati in altri container (Panel). Un Container è un contenitore di componenti, che dispone al suo interno utilizzando una classe accessoria LayoutManager. Grazie ad essi un container può disporre i suoi elementi in vari modi; quelli standard sono a griglia (GridLayout), a croce (BorderLayout) oppure affiancati (FlowLayout); ne esistono altri più sofisticati, ma anche utilizzando solo questi si può fare molta strada. La cosa importante è che i Container sono annidabili: per esempio una finestra con un BorderLayout può contentere un pannello che utilizza un FlowLayout e un altro con un GridLayout. A loro volta i pannelli possono contenere altri pannelli e così via. Questa struttura rende però abbastanza difficile l’editing visuale. Non si tratta solo di posizionare degli elementi su una griglia a certe coordinate: si tratta si organizzare l’interfaccia in una gerarchia di contenitori dentro altri contenitori.

Per facilitare l’editing, Jbuilder mette a disposizione una rappresentazione ad albero, il Component Tree, che viene visualizzata contemporaneamente al preview dell’interfaccia risultante.





In Figura 3 è visibile un esempio che dovrebbe chiarire il meccanismo. L’interfaccia mostrata in figura è composta da un Frame con un BorderLayout che contiene due pannelli, uno con un GridLayout e l’altro con un FlowLayout. Questa struttura è abbastanza comprensibile se si osserva la rappresentazione ad albero in figura a sinistra. È importante notare che l’inserimento dei componenti dell’interfaccia può essere fatto anche cliccando sulla rappresentazione ad albero, e questo spesso è un grande aiuto. Per esempio, per inserire un componente in un determinato pannello occorre selezionare un componente dalla palette e cliccare sul pannello dove lo si vuole inserire sull’albero.

Nonostanza sia disponibile l’albero dei componenti, occorre stare attenti a non abusarne. Data la particolare tecnica di composizione delle interfacce di Java, è facile ritrovarsi con un albero di componenti molto annidato, che è comunque difficoltoso da gestire. L’approccio migliore è invece quello di suddividere i componenti di una form complessa in varie form, editarli separatamente e poi assemblarli.





Per esempio in Figura 4 possiamo vedere un TabsetPanel che contiene al suo interno diversi pannelli, uno per ogni tab. Ogni pannello è editato come form separata, creando una nuova classe basata su Panel invece che su Frame. Il problema si pone quando si cerca di “assemblare” il tutto. Siccome i nuovi componenti non sono disponibili sulla palette, per inserire i propri pannelli si deve ricorrere all’editing manuale del codice oppure all’aggiunta di un nuovo componente in una toolbar. Mi sembra che il modo più semplice sia il seguente.

Supponiamo di aver creato un MovimentiPanel da Panel. Per inserirlo in un altro contenitore, per esempio un TabsetPanel, la cosa migliore è inserire un semplice Panel (rinominandolo per esempio movimenti per trovarlo facilmente nel codice). Questo genera gran parte del codice necessario per l’aggancio. A questo punto si va su source, si cerca (control-F):


Panel movimenti = new Panel();


e si cambia con:


MovimentiPanel = new MovimentiPanel();


Tutto il resto del codice, che inserisce il nuovo pannello al posto giusto (la parte più noiosa da scrivere a mano) rimane valido. In alternativa si può sempre andare su Tools | Configure (o cliccare col bottone destro sulla toolbar e selezionare properties), e aggiungere il nuovo pannello come componente alla toolbar, per poi inserirlo al posto giusto con un semplice drag n drop.

Un problema frequente è quello di produrre una decente “maschera” per l’input di molti campi disposti in maniera regolare, problema tipico per le schede di database, come quella visibile in Figura 4. La soluzione ovvia è quello di utilizzare un GridLayout, ma non va bene: questa soluzione ha il difetto di allargare i campi di input alla intera larghezza della cella. Il risultato, orribile, è che si ottengono campi di input che si allargano quando l’utente ridimensiona la finestra invece di mantenere la loro dimensione.

Una soluzione migliore è invece quella di utilizzare un GridLayout contentente dei FlowLayout in ogni cella: in questo modo basta una cella per riga se si sa come “allineare” i componenti contenuti in ogni cella. Purtroppo le Label e i LabelControl inserite in un FlowLayout vengono “schiacciate” alla loro “preferred size”. Di conseguenza ogni label ha una dimensione diversa a seconda del loro testo. Cambiare la dimensione esplicitamente non risolve il problema, il FlowLayout schiaccia sempre ogni componente alla preferredSize. Questo rende impossibile allineare per esempio Descrizione e Categoria come in Figura 4. La migliore soluzione che ho trovato è ricorrere ad una classe Label modificata come segue:


import java.awt.*;
public class FixedLabel extends Label {
  public Dimension preferredSize() { return getSize(); }
}

Con questo trucco si riesce ad inserire in un FlowLayout delle Label che mantengono la loro dimensione, operazione necessaria per riuscire ad allineare semplicemente ed agevolmente le Label quando sono poste in un FlowLayout. Tra l’altro la classe così modificata può essere inserita nella toolbar. Sull’argomento interfacce utenti si potrebbero dire molte altre cose, ma per il momento ci fermiamo qui, per andare a esaminare l’aspetto “accesso ai dati”.


ePrometeus s.r.l. - Web Software House & Open Source System Integrator
MILANO - SAN BENEDETTO DEL TRONTO(AP)
Contatti: info@eprometeus.com