|
|||||||||||||||||||||||||||||||||
Dopo aver tanto faticato a scrivere il nostro programma GUI in Java con AWT ecco che il rilascio di Swing sembra costringerci a rifare tutto da capo... Ma forse non tutto è perduto: vediamo cosa dobbiamo conoscere per migrare facilmente da AWT a Swing |
|||||||||||||||||||||||||||||||||
Introduzione
Non era facilmente prevedibile, anche se forse lo si poteva intuire, che il linguaggio introdotto col Netscape 2.0 per visualizzare animazioni, Java, potesse diventare un giorno addirittura un concorrente di Windows. La portabilità del linguaggio e le basi, ben fondate, che ne garantiscono l'indipendenza dal sistema operative hanno permesso di ampliare notevolmente le librerie standard del linguaggio. Oggi la libreria di Java è così ampia e completa da offrire l'opportunità di sviluppare applicazioni complesse senza ricorrere in alcun modo a chiamate dirette del sistema operativo. Naturalmente nessuno realmente pensa che Java potrà sostituire Windows, Unix o altri sistemi operativi: infatti in ogni caso la libreria Java sfrutta il sistema ospite. Ciò nonostante Java sembra destinato a diventare il fondamento di una nuova generazione di applicativi che girano indifferentemente su una ampia gamma di sistemi operativi mantenendo la portabilità a livello di codice eseguibile. Ormai il linguaggio e la sua libreria sembrano aver raggiunto una maturità sufficiente per consentire lo sviluppo di applicazioni professionali e complete. Fino alla versione 1.1, la principale limitazione della libreria di Java riguardava l'interfaccia grafica, limitazione che è stata definitivamente superata col rilascio della Java Foundation Classes di cui parliamo in questo articolo. Ci limitiamo a ricordare che la risposta di Microsoft non si è fatta attendere: le Window Foundation Classes per Java, una complessa e ricca libreria per Java, basata però su Win32. In ogni caso la JFC comprende varie API: noi ci occuperemo in particolare della libreria Swing che è un sottoinsieme della JFC. Motivazioni della Swing
Caratteristiche della Swing
In Figura 1 possiamo
vedere le caratteristiche multi look delle Swing in azione. Si tratta di
tre schermate di uno stesso programma che cambia dinamicamente il look
and feel selezionando un radiobutton. Notare come al variare del look cambino
dettagli come l'aspetto dei bottoni, il colore dello sfondo, il font utilizzato
per le label , il cursore dell'elemento selezionato corrente.
Principali componenti Swing Ci riferiremo
ai vari componenti chiamandoli con il nome che viene dato loro nella Swing.
Una caratteristica importante è che tutti i componenti di interfaccia
grafica della Swing hanno un nome che comincia per J. La ragione tecnica
di questa scelta è di distinguere i componenti Swing da quelli AWT
(che hanno molto spesso lo stesso nome), e consentire una semplice migrazione
dalla AWT. Ogni sforzo è stato fatto perché ogni nuovo componente
della Swing corrisponda ad un componente esistente nella AWT, e perché
esso si comporti allo stesso modo. In questo modo avendo una applicazione
AWT è possibile convertirla in applicazione Swing semplicemente
rinominando i componenti per aggiungervi una J in testa.
Entriamo ora
in dettaglio e descriviamo i principali componenti Swing. Le label, innanzitutto,
sono stringhe di testo che vengono inserite nelle interfacce utente. Logicamente
sono relate ai bottoni e ne condividono molte caratteristiche: in un certo
senso una label è un bottone che non può essere cliccato.
Sono disponibili quattro tipi di bottoni: i tradizionali bottoni, i checkbox
(bottoni selezionabili e deselezionabili), i radiobutton (bottoni che agiscono
in gruppo, in modo che selezionandone uno si deseleziona automaticamente
qualunque altro bottone del gruppo) e i nuovi bottoni "toggle", che assumono
e mantengono un nuovo stato ogni volta che vengono premuti. A differenza
della AWT tutti i bottoni e le label Swing hanno caratteristiche grafiche
avanzate: innanzitutto ciascuno di questi componenti può visualizzare
sia una stringa di testo che una immagine (correttamente chiamata icona).
Le icone possono essere inserite prima o dopo il testo, ed è possibile
impostare l'allineamento della icona rispetto al testo in orizzontale e
in verticale. Le icone sono gestite dalla classe JIcon, che supplisce
alle limitazioni della classe Image usata nella AWT per gestire
le immagini. La classe Image ha un uso abbastanza complesso (occorre
gestire gli eventi per disegnarle) e una procedura di caricamento piuttosto
fastidiosa. Tutte queste complessità vengono risolte da JIcon, che
è di uso semplicissimo: il programmatore deve soltanto specificare
una proprietà che indica il file da cui deve venire caricata l'icona.
Altra innovazione importante è l'introduzione degli "acceleratori"
di tastiera, ovvero i tasti che possono essere premuti per attivare il
bottone senza ricorrere al mouse (e che vengono visualizzati come una lettera
sottolineata); naturalmente si può definire un acceleratore per
ogni tipo di bottone.
I menu Swing
sono notevolmente più potenti di quelli AWT: è possibile
associare immagini ad ogni voce di menù (concettualmente i JMenuItem
sono pure dei bottoni, quindi hanno le stesse proprietà relative
all'uso di icone) e gli acceleratori di tastiera. Sono state aggiunte (finalmente!)
le toolbar, che sono forse una della più sentite mancanze della
AWT tanto sono comuni nelle GUI moderne. Nelle toolbar possono essere inseriti
componenti di qualunque tipo (normalmente bottoni ma anche campi di input
o liste di selezione a discesa) e se la interfaccia utente sottostante
la supporta, possono essere fluttuanti, ovvero sganciabili e posizionabili
liberamente.
Sono presenti
innanzitutto i bordi semplici come le linee, ma anche quelli più
"alla moda", che consentono di dare un look 3d alle applicazioni. I bordi
possono presentare anche dei titoli, possono essere posizionati e allineati
come si desidera e si può selezionare il font. Notare che il bordo
può essere composto da una immagine ripetuta, più o meno
come avviene con lo sfondo dei desktop. Effetti sofisticati sono ottenibili
componendo più bordi: per esempio combinando un bordo a bassorilievo
con una opportuna figura si può ottenere un simpatico effetto di
cornice. Altri componenti degli di nota sono le slider (barre simili
ai regolatori del volume negli impianti ad alta fedeltà), che consentono
di selezionare un valore in un certo intervallo numerico, e le progress
bar (barre che mostrano il punto in cui si è arrivati nell'esecuzione
di una operazione che richiede un certo tempo).
Pannelli e Layout
I contenitori
AWT e Swing sono di due tipi: finestre e pannelli. Le finestre sono dei
contenitori che hanno una autonomia: creano appunto una nuova finestra.
I pannelli invece sono dei particolari contenitori che devono essere contenuti
in una finestra, e visualizzano in modo particolare i componenti che contengono.
Tanto per fare un esempio la toolbar Swing è un particolare tipo
di contenitore. La AWT mette a disposizione due soli tipi di pannello (il
Panel e lo ScrollPane), mentre la Swing è molto più ricca.
Consideriamo
ora qualcuno dei nuovi componenti della Swing. Innanzitutto abbiamo il
JTabbedPane,
un pannello che consente la selezione dei componenti che contiene tramite
linguetta. Questo pannello è visibile per esempio in figura 3. Un
altro interessante pannello è il JScrollPane, che consente
ai componenti che contiene (tipicamente immagini) una visualizzazione parziale
e scrollabile. La AWT 1.1 possiede un componente analogo, lo ScrollPane,
ma quello della Swing è più ricco in quanto consente di personalizzare
i righelli e di controllare in maniera più accurata l'area visualizzata.
Il JSplitPane infine consente di dividere una finestra con un divisore:
al contenitore possono essere aggiunti due componenti che vengono ridimensionati
a seconda di come l'utente sposta il divisore. È simile in un certo
senso ai frame delle pagine Web.
Windows ci ha abituati da anni alle finestre "annidate", ovvero finestre contenute dentro altre finestre. Si tratta della cosiddetta interfaccia MDI (Multiple Document Interface), che per anni non ha avuto eguali nelle altre interfaccie grafiche come per esempio il Mac o Motif. Swing mette a disposizione anche la possibilità di costruire applicazioni MDI grazie all'uso del JInternalFrame Finora abbiamo
visto molti dei componenti ma ancora non abbiamo esaminato una aspetto
importante che differenza sostanzialmente le finestre AWT (Frame)
da quelle JFC (JFrame). Mentre è possibile con la AWT aggiungere
elementi direttamente ad un Frame, ogni JFrame contiene due pannelli
sovrapposti, uno detto rootPane e l'altro glassPane, e bisogna
aggiungere esplicitamente i componenti di una finestra al rootPane. In
pratica invece di scrivere jframe.add(button) occorre usare il codice
jframe.getContentPane().addButton().
Questa caratteristica è giustificata dalla necessità di supportare
componenti che si sovrappongono all'interfaccia utente abituale. Per esempio
i menù popup o i tooltip. Grazie alla scelta di sovrapporre due
pannelli in ogni finestra si risolve elegantemente in problema. Ogni elemento
che fa parte dello sfondo della finestra viene disegnato nel rootPane,
mentre ogni altro elemento che appare provvisoriamente e poi scompare sfrutta
il glassPane.
Modello Documento-Vista La Swing ci mette
a disposizione alcuni componenti abbastanza complessi: per la precisione
abbiamo gli "outline" (rappresentazione grafica di alberi) e le griglie
(rappresentazione grafica di matrici). Per l'utilizzo di questi componenti
diviene fondamentale sfruttare un altro importante aspetto della JFC che
non è stato ancora esaminato: l'architettura Documento Vista. Questa
architettura è una delle caratteristiche principali del sistema
GUI del linguaggio Smalltalk, dove prende il nome di Model View Control.
Questa archiettura è stata in seguito ripresa in altre librerie
come le MFC di Visual C++, ed infine incorporata nelle Swing di Java. Una
descrizione dettagliata di come funzioni questo modello esula dai limiti
di questo articolo.
Ci limitiamo
a descrivere cosa comporta e quali vantaggi ha per il programmatore. Per
ogni componente è possibile separare la struttura dati visualizzata
da un componente dal componente stesso. In generale per componenti semplici
questo non ha grande importanza, mentre ne ha per componenti complessi
quali le tabelle o gli alberi. Supponiamo quindi di voler visualizzare
in una tabella il risultato di una interrogazione di un database. Senza
il modello MVC, occorrerebbe prendere i risultati dal database e inserirli
nel componente uno per uno per presentarli all'utente; qualora l'utente
modifichi la tabella, occorre esaminare il contenuto del componente e riportarlo
nel database. Sfruttando MVC e seguendo gli standard della Swing è
possibile definire una struttura dati e associarla al componente: la modifica
di questa struttura dati si ripercuote automaticamente sul componente,
e viceversa la modifica del componente si ripercuote sulla struttura dati.
In questo modo è possibile separare nettamente la logica di interazione
con l'utente (che è essenzialmente gestione di eventi) dalla logica
di modifica dei dati. Come esempio consideriamo la visualizzazione di una
griglia che contiene dati di un database come in Figura 8.
Il programmatore
separa il codice che gestisce l'interazione col database (che rappresenta
il modello) dal codice che gestisce l'interazione con l'utente (la vista).
In pratica occorre sviluppare una classe che implementa l'AbstractTableModel:
questa classe si occuperà di aprire la connessione e memorizzare
i risultati. L'aggancio con la griglia avviene semplicemente impostanto
il modello che la griglia visualizza (con setModel). Notare che
in questo modo il codice che gestisce l'interfaccia rimane integralmente
valido anche se il programmatore decide di cambiare la fonte dati, utilizzando
un file invece che un database, e occorre soltanto cambiare il modello.
Analogamente si può riutilizzare il codice del modello nell'interazione
col database agganciandolo ad una interfaccia utente completamente diversa.
Conclusioni
|
|||||||||||||||||||||||||||||||||
Michele Sciabarrà è autore, consulente e formatore. Quando non scrive o tiene corsi coordina lo sviluppo software della Prometeus, ditta di cui è titolare. Il suo ultimo libro è "Linux e Programmazione Web" (McGraw-Hill). Si occupa di Java dalla versione alpha, di Linux dalla versione 0.99 e di programmazione dai tempi del Commodore 64 | |||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||
|