Introduzione
Poco prima della
pausa estiva mi è stato chiesto di realizzare una “semplice” applet
che svolgesse funzioni di editor HTML. L’applet in questione
doveva permettere di produrre un documento HTML, sia creandolo ex
novo, sia importandolo con un semplice copia ed incolla dalla clipboard.
Il funzionamento
doveva essere in tutto e per tutto simile ad un comune word processor,
e doveva essere inoltre possibile al termine del lavoro, il salvataggio
in formato HTML (più precisamente il brano finito doveva essere
salvato in un archivio elettronico residente su un server remoto).
Le operazioni
di base dovevano permettere di inserire parti in grassetto e corsivo, di
effettuare l’allineamento nelle tre posizioni principali (destra, sinistra,
centrato), di associare a certe parole o frasi del testo link ipertestuali,
secondo la maniera classica del formato HTML.
Per poter realizzare
una cosa del genere, si possono seguire due strade differenti: la prima
consiste nel partire da un semplice editor di testo, ed aggiungerci
le funzionalità di cui sopra, associando a certe parti del
brano i tag HTML corrispondenti (come <B> per il grassetto o <I>
per il corsivo ). In questo caso la difficoltà consiste nel realizzare
a mano il cosiddetto WYSIWYG, ovvero mantenere costantemente allineate
le due versioni del documento: quella a video (del testo formattato)
e quella in memoria (codice HTML).
Questo modo
di operare è molto simile al Model View Control (MVC) utilizzato
dalle Swing classes, ed è di fatto la soluzione più elegante
per ottenere il risultato voluto.
Come il lettore
potrà immaginare realizzare e soprattutto gestire una struttura
del genere è tutt’altro che semplice: si pensi infatti a cosa si
deve fare nel caso in cui l’utente prema il tasto back space, o con
il mouse si posizioni in un punto qualsiasi del testo, effettuando magari
delle modifiche.
Mentre infatti
l’aggiornamento a video può essere più o meno semplice, la
modifica contemporanea della parte HTML risulta essere piuttosto complessa.
Per realizzare l’editor HTML non seguiremo questa strada, anche se, nel
proseguo dell’articolo, la riprenderemo in considerazione per mostrare
come risolvere certe problematiche derivanti da un non corretto funzionamento
di alcuni componenti Swing.
La soluzione
presentata sicuramente è eccessivamente complessa, soprattutto prendendo
in considerazione ciò che Java ci offre: la regola numero uno di
un buon programmatore Java è infatti quella di non inventare niente
di nuovo se già si può disporre di qualcosa di già
pronto (in realtà dovrebbe essere la regola di ogni programmatore,
ma per come sono state implementate le classi del JDK, in Java questo concetto
è particolarmente sentito): possiamo prendere quindi in considerazione
alcune classi contenute nelle classi Swing: in particolare nel nostro
caso le classe che ci serviranno sono l’HTMLEditorKit, e la JEditorPane.
Swing Classes
ed MVC
Le classi Swing
facenti parte del più ampio insieme denominato Java Foundation Classes,
e sono un set di componenti grafici avanzati che con il tempo dovrebbero
sostituire le corrispondenti AWT. I nuovi componenti grafici si distinguono
dai precedenti per alcuni fattori molto importanti. Per prima cosa
si deve notare che, a differenza dei componenti dell’AWT, i vari componenti
grafici sono stati totalmente riscritti in Java, e per questo motivo non
hanno bisogno di accedere alle risorse di sistema. Ad esempio un pulsante
viene totalmente disegnato e gestito dalla VM, e non dal motore grafico
messo a disposizione dal sistema operativo. Questo ha permesso di creare
dei componenti grafici più potenti, versatili, e senza dubbio più
piacevoli alla vista (per una introduzione veloce sul confronto fra SWT
e Swing si consulti [GUIs]
Un altro fatto
degno di nota è il nuovo modello di gestione utilizzato dai componenti
Swing. Il Model View Controller infatti rappresenta un interessante passo
avanti rispetto al passato. Nel riquadro “L’architettura di MVC”
si può trovare una breve spiegazione di cosa sia questo sistema
e come mai sia tanto importante.
Nel nostro caso
questo sdoppiamento (anche se in teoria la suddivisione è in tre
parti di cui due però sono raggruppate), è particolarmente
utile proprio per il tipo di applicazione da realizzare.
Infatti, ripensando
anche a quanto accennato nella prima parte dell’articolo, avere un qualche
sistema che visualizzi a video l’HTML interpretato, ma ne mantenga la struttura
in memoria in modo da potervici accedere in ogni momento si adatta piuttosto
bene all’MVC.
Nelle Swing
classes è presente un componente denominato JeditorPane, il quale
è in grado di visualizzare documenti in formati particolari eseguendo
in automatico l’interpretazione del formato: al momento i formati disponibili
sono l’RTF e l’HTML.
In pratica,
con pochissime righe di codice è possibile creare un interprete
di codice HTML, e con qualche sforzo in più un piccolo browser.
Vediamo quindi
per prima cosa come fare per realizzare qualcosa di più semplice,
ovvero l’interprete HTML, per poi passare all’editor.
MiniBrowser
Per poter comprendere
come il JEditorPane possa interpretare codice HTML (per brevità
ci concentreremo solo su questo formato, ma per chi volesse utilizzare
l’RTF, i ragionamenti sono del tutto identici), dobbiamo prima fare una
breve analisi della sua struttura.
Anche se in
realtà la sua struttura interna è più complessa di
come la descriveremo, struttura peraltro del tutto trasparente al programmatore
finale, si può immaginare il componente come composto da due strati:
il documento che rappresenta il contenuto informativo in un certo formato
da visualizzare, e quello lato utente che di fatto effettua la rappresentazione
del documento.
Nel mezzo troviamo
una specie di traduttore che di fatto esegue la trasformazione ad esempio
da HTML a documento formattato. Nella Figura 1 troviamo una schematizzazione
di tale organizzazione.
|
Figura
1 Schema
di funzionamento dell'editor html
In questo caso
si possono facilmente individuare i tre componenti dello schema MVC: in
particolare l’accoppiata traduttore-visualizzatore permettono di definire
come il documento verrà visualizzato (View), mentre il contenuto
del documento può essere facilmente ricondotto al Model.
La struttura
stratificata JEditorPane è data dal componente stesso, dal
documento ivi contenuto, e dal particolare EditorKit installato. Quest’ultimo
in particolare è l’elemento fondamentale che permette di visualizzare
l’HTML.
Vediamo quindi
cosa è necessario fare per realizzare un semplice visualizzatore
HTML: per prima cosa si deve creare una istanza della classe JEditorPane,
cosa piuttosto semplice come mostrato qui di seguito
JEditorPane
text = new JEditorPane ();
text.setContentType("text/html");
text.setEditable(false);
La prima
riga semplicemente dichiara ed istanzia un JEditorPane, mentre
la seconda serve per impostare il tipo di documento che vogliamo trattare.
In questo caso si specifica il formato HTML: se ci fossimo dimenticati
di effettuare tale operazione, il JEditorPane avrebbe visualizzato il codice
HTML, senza effettuarne la trasformazione in testo formattato.
Il metodo setContentType
di fatto causa la creazione dell’EditorKit appropriato e lo installa nel
componente stesso. Il run time sa che al formato “TEXT/HTML” è associato
l’HTMLEditorKit. Avremmo quindi potuto scrivere equivalentemente
HTMLEditorKit
he = new HTMLEditorKit()
text.setEditorKit(he);
Adesso possiamo
passare a “immettere” il codice HTML all’interno del JEditorPane.
Per fare questo, il metodo più sicuro ed efficace è quello
di utilizzare il documento (classe Document) contenuto al suo interno.
Se ad esempio la stringa html_code contiene il codice HTML
CharArrayReader
car= new CharArrayReader(html.toCharArray());
Document
doc= text.getDocument();
EditorKit
ed= text.getEditorKit();
ed.read(car,
doc, 0);
Queste poche
righe di codice sono praticamente il cuore del programma che vogliamo realizzare:
il metodo
getDocument
estrae il documento dal JEditorPane, così come il getEditorKit ci
permette di ottenere l’editor precedentemente installato. Tramite l’editorkit
si può quindi effettuare l’immissione dell’HTML dentro il documento
(vedi metodo read).
Adesso abbiamo
creato un minimale visualizzatore di codice HTML: per completare il mini
browser è sufficiente creare una qualche interfaccia grafica, ed
un piccolo file-downloader, che permetta di scaricare un file HTML prelevandolo
da un qualche sito remoto.
Dato che si
tratta di due compiti piuttosto semplici, non ci soffermeremo su questi
due aspetti, che sono peraltro ben documentati nell’esempio qui di seguito
MyBrowser.java.
import
com.sun.java.swing.*;
import
com.sun.java.swing.event.*;
import
java.awt.*;
import
java.awt.event.*;
import
java.io.*;
import
java.util.*;
import
java.net.*;
public
class MyBrowser extends JPanel{
// le dimensioni iniziali del frame
public static int WIDTH = 600;
public static int HEIGHT = 400;
//i componenti grafici pr la costruzione della GUI
protected JEditorPane vista;
protected JTextField urls;
public MyBrowser(){
vista = new JEditorPane();
vista.setEditable(false);
//Si aggiunge un listener per la gestione dei link
vista.addHyperlinkListener(new HyperlinkListener(){
//Questo metodo è chiamato al click su un hyperlink
public void hyperlinkUpdate(HyperlinkEvent event){
setURL(event.getURL());
}
});
setLayout(new BorderLayout());
add(vista,"Center");
// Aggiunge il campo per l'inserimento degli indirizzi
urls = new JTextField();
add(urls,"North");
//Si crea l'ascoltatore
urls.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae){
try{
URL newURL = new URL(ae.getActionCommand());
setURL(newURL);
}
catch (MalformedURLException mue){
System.out.println("L' URL inserito non è
corretto:"+mue);
}
}
});
}// fine MyBrowser
public void setURL(URL newURL){
try{
vista.setPage(newURL);
urls.setText(newURL.toExternalForm());
}catch (IOException ioe){
System.out.println("Error :"+ioe);
}
}// fine setURL
public static void main(String s[]) {
MyBrowser panel = new MyBrowser();
JFrame frame = new JFrame("Mini browser HTML");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
frame.getContentPane().add("Center", panel);
frame.pack();
frame.setVisible(true);
frame.setSize(WIDTH,HEIGHT);
}// fine main
}
Editor HTML
Fino ad ora
non abbiamo fatto niente di particolarmente complicato, utilizzando per
la maggior parte le funzionalità delle classi Swing messe a disposizione.
In realtà
anche quello che vedremo fra poco non dovrebbe richiedere particolari accorgimenti,
se non fosse per il fatto che, a causa di alcune imperfezioni di implementazione
(bug), è necessaria un po’ di astuzia per inventarsi
qualche trucco.
Per modificare
un documento HTML in definitiva abbiamo bisogno di alcuni comandi con cui
pilotare il JEditorPane (o meglio per poter modificare il documento inserito).
E’ infatti piuttosto complesso agire a mano sul codice HTML.
|
Figura
2 L'editor in funzione
Fortunatamente
l’oggetto JEditorPane dispone di una serie di Actions (una action è
una specie di Listener, che permette di propagare eventi e comandi) con
le quali effettuare le operazioni tipiche di editing sul documento.
L’elenco delle
azioni disponibili (che variano in funzione della versione delle
Swing utilizzata) è utilizzabile per mezzo del metodo JEditorPane.getActions(),
che restituisce una array di Action.
Fra le molte
possiamo sicuramente ricordare la paste-from-clipboard (effettua
un incolla dalla clipboard), left-justify (allineamento a sinistra) o la
font-italic (imposta il font in corsivo).
Per poter essere
utilizzata una Action può essere associata ad esempio ad un
bottone contenuto in una toolbar. Ad esempio
AbstractAction
pasteAction = (AbstractAction) commands.get ("paste-from-clipboard");
button
= bar.add(pasteAction);
button.setText("");
img =(Image)
ImgsTable.get("paste");
icon=
new ImageIcon(img);
button.setIcon(icon);
button.setToolTipText("Incolla");
dove commands
è una hashtable contenente tutte le actions disponibili (caricata
in automatico, vedi esempio allegato), bar è una toolbar e
ImgsTable una altra hashtable contenente le icone da associare ad ogni
pulsante. Nel riquadro “le Swing Actions” sono riportate tutte
le actions delle Swing 1.0.
A questo
punto alla pressione di uno dei pulsanti della toolbar, verrà eseguita
direttamente sul codice HTML l’operazioni corrispondente.
Quindi con poche
linee di codice, la maggior parte delle quali dedicate alla realizzazione
della interfaccia grafica, è possibile creare un editor HTML minimale
ma perfettamente funzionante, almeno in teoria.
Il problema
principale infatti è che alcuni degli eventi (actions) a disposizione
non svolgono perfettamente o affatto il loro compito.
Ad esempio l’allineamento
a dx/sx/centrato non funziona correttamente con le Swing 1.0.
Fra tutti, i
maggiori problemi li ho incontrati con nella parte relativa alla gestione
dell’inserimento dei link: task di primaria importanza per un editor anche
banale, a seconda della particolare funzione, della versione di Swing,
e a volte anche del browser, spesso i risultati non sono sempre gli stessi,
ed a volte del tutto indesiderati.
Senza entrare
troppo nei dettagli dei vari tipi di malfunzionamento e delle loro possibili
cause, diciamo che in questo caso, almeno utilizzando il software in mio
possesso (release che dovrebbero essere presto aggiornate), la soluzione
ai vari problemi è stata quella di agire a mano e direttamente
sul codice HTML.
Le operazioni
descritte qui di seguito potranno apparire piuttosto macchinose,
certamente non molto in linea con la filosofia OOP e lontane dall’eleganza
di Swing e del modello MVC. In effetti sono queste critiche più
che giustificabili, ma ho voluto comunque riportare queste tecniche di
lavoro per dare un’idea sia di come funzioni dentro il sistema, sia per
ovviare a reali malfunzionamenti o comportamenti indesiderati. Inoltre
l’analisi di tali tecniche potrà essere utile anche per comprendere
certi dettagli di Swing e di MVC..
Inserire un
link a mano
Per inserire
un link in una pagina HTML, è sufficiente modificare il codice HTML
in modo che contenga il tag <A> con tutti i parametri settati opportunamente.
Ad esempio un link potrebbe essere
<A
HREF=url_link >parola da lineare </A>
Per inserire un
link associato ad una certa parola quindi sarà necessario selezionare
n caratteri ed associare a tali caratteri un url.
Prima di procedere
vediamo di fare alcune considerazioni su come possiamo interagire con il
documento HTML: da una parte abbiamo il testo (per intendersi quello visualizzato
dal viewer HTML), dall’altro il codice HTML
Sul primo possiamo
effettuare le operazioni direttamente di selezione ed edit con mouse e
tastiera, mentre agendo sul secondo possiamo modificare fin nei dettagli
il codice a nostro piacimento.
Per inserire
il link abbiamo detto che la prima cosa da fare è selezionare una
parola e poi modificare il codice inserendo il tag <A>.
Primo problema:
solo dal testo si può sapere quale parola è stata selezionata,
ma solo agendo sul codice possiamo modificare l’HTML esattamente nel modo
voluto. Si deve quindi trovare un modo per mettere insieme le due
cose, arrivando a trasformare l’HTML. Questa potrebbe essere la procedura
da seguire:
-
inserire un metatag
nel testo: ricavando la parola selezionata dall’utente con il mouse, la
si può evidenziare in modo che anche a livello di HTML sia evidenziabile.
Infatti se si lavora a livello di codice non è possibile ottenere
nessuna informazione su cosa l’utente ha selezionato. Per evidenziare la
parola è possibile “virgolettarla” con due metatag particolari come
“$_” + parola + ”_$”. Il codice per fare questo tipo di operazione
potrebbe essere
String
txt=text.getText();
int start_sel=text.getSelectionStart();
int end_sel=text.getSelectionEnd();
String
selected=text.getSelectedText();
text.replaceSelection("$_"+selected+"_$");
-
Ricavare il
codice e modificarlo è la seconda operazione da effettuare: per
ottenere il codice HTML dall’EditorKit , si può effettuare una operazione
del tutto simmetrica a quella vista in precedenza per l’immissione
CharArrayWriter
caw=new CharArrayWriter ();
ed.write(caw,doc,0,doc.getLength());
String
html_code =caw.toString();
-
Successivamente
si effettua la modifica sull’HTML come voluto: dopo aver individuato la
posizione della parola “virgolettata” con $_ _$
int
end_link= html_code.indexOf("_$");
int start_link=html_code.indexOf("$_");
-
si può immettere
il tag corrispondente al link
html_code=html_code.substring(0,end_link)+"</A>
"+html_code.substring(end_link+2);
html_code
=html_code.substring(0,start_link);
html_code
= html_code +" <A HREF="+link_url+">"+html_code.substring(start_link+2);
-
Infine si
deve procedere alla reimmissione del codice HTML modificato all’interno
dell’EditorKit. Questa operazione la si può effettuare in maniera
del tutto analoga a quanto visto in precedenza: almeno di disporre di
processore e scheda video lenti, non occorre nascondere il JEditorPane
per nascondere le variazioni che si effettuano in chiaro.
E’ importante
notare che l’operazione di reimmissione del testo effettua un append rispetto
al testo originale: per far si che si esegua una sostituzione, si deve
prima ripulire il JEditorPane, e poi riscriverci dentro.
Fra tutte le
possibili soluzioni adottabili per ottenere questo, l’unica che ha funzionato
durante le mie prove consiste nel creare un documento (classe Document)
nuovo e dunque dal contenuto vuoto dunque, ed assegnarlo al JEditorPane
prima di reimmettere il testo modificato: si può utilizzare per
questo il metodo JEditorPane.setDocument().
Bug e plug-in
Come ho avuto
modo di accennare in precedenza, durante la realizzazione di questa applet
ho potuto riscontrare spesso comportamenti strani, e del tutto inaspettati.
Le differenze fra le varie versioni delle Swing, del JDK e del browser
hanno contribuito a tali comportamenti non propriamente ortodossi.
Quella che ho
potuto sperimentare come la configurazione migliore è composta dalle
classi Swing 1.0, JDK 1.1 (pur essendo disponibili Swing 1.1 e JDK 1.2)
ed il Java Plug-in: dato infatti che si richiedeva la realizzazione di
una applet, che seppur funzionante con i browser 4.xx, l’utilizzo del plug-in
si è reso necessario sia per uniformare il comportamento della applet
al cambiare del sistema operativo e browser, sia per fixare certi problemi.
Sicuramente
al momento in cui questo articolo verrà pubblicato, la situazione
dovrebbe essere migliore e l’adozione dei browser 5.xx, del JDK 1.2 e quindi
delle Swing 1.1, risolverà la maggior parte dei problemi che invece
ho adottato io.
Caratteri
pericolosi
In fase di utilizzo
della
applet sono saltati fuori numerosi problemi soprattutto in fase di inserimento,
per mezzo del copia/incolla , di brani già pronti prelevati da altri
programmi.
Il problema
in questo caso era dovuto alla presenza di certi caratteri non stampabili,
e non interpretabili in ogni modo in HTML, che venivano importati dal programma
utilizzato per scrivere il brano.
Tali caratteri
possono portare alla generazione di una eccezione in fase di immissione
del testo all’interno dell’EditorKit: infatti è bene tener presente
che il codice HTML deve essere ben formattato, e sintatticamente corretto,
dato che il parser in questione è molto scrupoloso e pignolo.
Per ovviare
a tali inconveniente, si può agire in due modi: la prima soluzione
è quella di ripulire il testo da tutti quei caratteri non “graditi”
prima di effettuare l’immissione. Tale tecnica offre sicuramente tempi
minori rispetto all’altro metodo, ma non è applicabile se non si
conoscono esattamente tutti i caratteri che possono dare problemi.
Dato che il
caso è tipicamente proprio questo, si può ricorrere all’altro
metodo, che è quello di “catchare” l’eccezione generata, ricavare
il codice del carattere causa di tutto (fortunatamente l’eccezione generata
ci fornisce anche questa indicazione) e di sostituirlo/eliminarlo.
In pratica il
meccanismo consiste nell’individuare un carattere dannoso, eliminarne tutte
le occorrenze e provare a reimmettere il testo. Questa operazione
si ripete n volte fino a che non si generano più eccezioni.
Per sapere quale
è il carattere pericoloso si può interpretare il messaggio
di errore che ci fornisce il codice Ascii e Unicode: ad esempio una eccezione
di questo tipo genere un messaggio del tipo
Eccezione
:java.io.IOException:
HTML Parse
Error:
Lexical
error at line 1, column 17.
Encountered:
"\u2019" (8217), after : ""
Questo sistema
sicuramente è un intrinsecamente lento, dato che deve eseguire m
cicli tanti quanti sono i tipi di caratteri non riconosciuti. E’ però
sicuro, nel senso che non soffre di dimenticanze da parte del programmatore
che magari non conosce tutti i caratteri che possono dare problemi.
L’unico vero
problema di tale procedura è il fatto che si affida alla stringa
di errore, messaggio che può essere suscettibile di cambiamenti
futuri: operando su tale fattore è possibile rendere il tutto
più sicuro.
Come ricavare
il testo
Resta da vedere
come sia possibile ricavare il codice HTML per il salvataggio: nel
progetto commissionato, salvataggio significava salvare in un archivio
centralizzato. Per le restrizioni dovute al security manager cui ogni applet
deve sottostare, questo obiettivo lo si può realizzare grazie all’utilizzo
di qualche riga di Javascript ed ad un banale cgi (Servlet, Perl o altro).
Per maggiori dettagli su questo punto si legga il riquadro “Java &C
un lavoro di squadra”
Conclusioni
Come si è
potuto vedere quindi grazie alle nuove funzionalità di Java, in
particolare alle classi Swing, la realizzazione di un progetto apparentemente
piuttosto complesso si è rivelata una operazione alquanto semplice.
Anche se molti
aspetti andrebbero migliorati, lo spunto di partenza credo che sia
sufficiente per iniziare a realizzare un prototipo funzionante, dal
quale poi sviluppare qualcosa di più articolato.
Il codice di
cui si parla nell'articolo lo si può prelevare qui
Bibliografia
[Jav12] “Using
Java 1.2”, J.L. Weber Ed. Que.
[JFC] “Core
Java Foundation Classes” do Kim Topley, Ed. Prentice Hall PTR
[GUIs] “MFC
Motif, Swing: confronto fra interfacce grafiche” – MokaByte 33 Sett 99
(www.mokabyte.it/1999/09/).
[MBSwing] “Corso
di Swing” – MokaByte 23 Ottobre 98 (www.mokabyte.it/1998/10)
e successivi.
Riquadro
1 - Java & C: il lavoro di gruppo semplifica le cose
Anche se a volte ho cercato di non
mescolare tecnologie e linguaggi di programmazione, preferendo l’eleganza
e la pulizia di soluzioni solo-Java, è indubbio che in certi casi
l’ausilio di strumenti esterni rende le cose molto più semplici.
Nel caso in questione, l’applet che
deve impaginare un brano in formato HTML, il passo finale vedeva la memorizzazione
in un archivio centrale situato sul server remoto dal quale l’applet viene
scaricata.
Per le limitazioni legate alla sicurezza
cui una applet deve sottostare, è piuttosto ovvio che tale
compito non può essere svolto dalla sola applicazione in esecuzione
nella JVM del browser. Si potrebbe quindi ricorrere ad una applicazione
lato server, la quale comunichi via socket con l’applet-client.
Anche se ormai tale tecnica è
abbondantemente utilizzata, e non riserva particolarità degne di
nota, si può utilizzare un’altra soluzione più semplice e
più veloce da realizzare.
Tramite un form HTML e del codice
Javascript infatti possiamo ricavare il testo dalla applet ed immetterlo
in uno dei campi testo del form stesso. Più precisamente alla pressione
del tasto invia del form HTML, prima della invocazione cgi, una semplicissima
funzione JS preleverà il codice dalla applet invocandone un metodo
(che deve essere pubblico per poter essere invocato dall’esterno) ed assegnandolo
ad un campo testo hidden del form.
A questo punto è sufficiente
che il CGI (un servlet, ma anche una applicazione scritta in C, Perl etc..)
prelevi il testo inserito nel campo testo e lo vada ad immettere ad esempio
nella tabella di un database.
Si ricordi che il tipo di action da
invocare deve essere POST e non GET, dato che quest’ultima limita a 255
caratteri la lunghezza massima dei parametri passati, e quindi il testo
del brano HTML molto probabilmente non rientrerebbe tutto in tale limite. |
Riquadro
2 - L’architettura di MVC
La principale differenza fra le classi
Swing e le corrispettive precedenti di AWT, è che le prime sono
scritte interamente in Java, per cui non dipendono dalla particolare implementazione
del motore grafico del sistema operativo sul quale vengono fatte eseguire.
La conseguenza più importante
è che adesso è possibile disporre di oggetti grafici il cui
aspetto, ma soprattutto il cui funzionamento, sia uniforme al variare della
piattaforma.
E’ importante comunque notare che
non si tratta di un semplice porting in Java, ma di un vero è proprio
processo di reingerizzazione, grazie al quale si è potuto adottare
un nuovo modello di gestione grafica e degli eventi detto Model View Controller
(in sigla MVC, dal nome dei tre principali costituenti).
Data l’importanza di questo modello,
senza scendere troppo nei dettagli, vediamo in breve cosa sia e come funzioni.
Come indica la sigla è essenzialmente
costituito da tre componenti il Model, il View ed il Controller: per capirne
la loro funzione, prendiamo in analisi per esempio un comune componente
grafico come un bottone.
Tutto quello che riguarda la sua rappresentazione
grafica (dimensioni, aspetto, look in genere) sono controllate dal cosiddetto
View, che in pratica potremmo pensarlo come un “disegnatore” dell’oggetto.
Più precisamente il View contiene le informazioni su come l’oggetto
deve apparire, demandando poi ad altri le effettive operazioni di paint.
Ma un bottone, come la maggior parte
dei vari widgets, possiede uno stato: in un certo istante infatti può
essere premuto o no, disabilitato, con il focus, e così via.
Molto sinteticamente allora lo stato
del componente lo associamo al Model del componente stesso.
Infine deve essere disponibile un
qualche soggetto, il Controller appunto, che monitori tutti gli eventi
generati dall’utente e quelli di sistema in modo da modificare l’aspetto
(o meglio lo stato, e quindi la sua visualizzazione) dell’oggetto.
Quando un bottone viene creato tutti
e tre i componenti vengono creati automaticamente (in realtà il
modello di Swing prevede un raggruppamento, ma dal punto di vista teorico
la base è proprio questa).
Per vedere come i tre elementi collaborano
fra loro, supponiamo che l’utente clicchi col mouse il bottone: in
tal caso il controller intercetta tale evento e procede ad avvertire il
Model che lo stato del componente deve essere cambiato (ovviamente anche
il codice della applicazione deve essere avvertita, ma in questo momento
non ci interessa).
Il Model quindi, propaga tali informazioni
al View che provvederà a modificare la visualizzazione del componente.
Se dal codice vogliamo comandare il
componente (ad esempio provocando un evento), agiremo sul Model direttamente.
Se invece vogliamo disabilitare il bottone, sempre agendo sul Model causeremo
una interruzione della propagazione dell’evento dal controller al Model,
per cui ogni click del mouse resterà inascoltato.
Anche se può non apparire scontato,
questo sistema apparentemente più complesso, ha il grosso vantaggio
di semplificare le cose, specie quando l’architettura diviene più
complessa. Ad esempio la modularità e la separazione fra M-V-C
permette di sostituire uno dei tre senza dover riprogettare e riscrivere
tutto da capo.
E’ proprio quello che accade nel caso
del pluggable-look & feel, introdotto con le Swing classes: si tratta
di un meccanismo che permette di impostare a priori il look della interfaccia
grafica, potendo scegliere (al momento) fra look alla Windows, look alla
Motif (Unix) o Metal (quello della figura 1). Al solito la modularità
di Java permette con un poco di lavoro aggiuntivo di fare molto di
più.
Per una analisi approfondita delle
Swing API e di MVC, approfondimenti si possono consultare [JFC]
e [MBSwing] |
|