Introduzione all'AWT

La libreria di classi del linguaggio di programmazione Java fornisce un toolkit dell'interfaccia utente chiamato Abstract Windowing Toolkit o AWT. L'AWT è potente e flessibile. I nuovi arrivati, tuttavia, spesso scoprono che il suo potere è velato. Le descrizioni delle classi e dei metodi trovate nella documentazione distribuita forniscono poche indicazioni per il nuovo programmatore. Inoltre, gli esempi disponibili lasciano spesso molte domande importanti senza risposta. Naturalmente, i nuovi arrivati ​​dovrebbero aspettarsi qualche difficoltà. Interfacce utente grafiche efficaci sono intrinsecamente impegnative da progettare e implementare e le interazioni a volte complicate tra le classi nell'AWT rendono solo questo compito più complesso. Tuttavia, con una guida adeguata, la creazione di un'interfaccia utente grafica utilizzando l'AWT non è solo possibile, ma relativamente semplice.

Questo articolo copre parte della filosofia alla base dell'AWT e affronta la questione pratica di come creare una semplice interfaccia utente per un'applet o un'applicazione.

Cos'è un'interfaccia utente

L'interfaccia utente è quella parte di un programma che interagisce con l'utente del programma. Le interfacce utente assumono molte forme. Queste forme variano in complessità dalle semplici interfacce della riga di comando alle interfacce utente grafiche punta e clicca fornite da molte applicazioni moderne.

Al livello più basso, il sistema operativo trasmette le informazioni dal mouse e dalla tastiera al programma come input e fornisce pixel per l'output del programma. L'AWT è stato progettato in modo che i programmatori non debbano preoccuparsi dei dettagli del tracciamento del mouse o della lettura della tastiera, né si occupino dei dettagli della scrittura sullo schermo. L'AWT fornisce un'interfaccia orientata agli oggetti ben progettata per questi servizi e risorse di basso livello.

Poiché il linguaggio di programmazione Java è indipendente dalla piattaforma, anche l'AWT deve essere indipendente dalla piattaforma. L'AWT è stato progettato per fornire un insieme comune di strumenti per la progettazione dell'interfaccia utente grafica che funziona su una varietà di piattaforme. Gli elementi dell'interfaccia utente forniti da AWT vengono implementati utilizzando il toolkit GUI nativo di ciascuna piattaforma, preservando così l'aspetto di ciascuna piattaforma. Questo è uno dei punti di forza dell'AWT. Lo svantaggio di un tale approccio è il fatto che un'interfaccia utente grafica progettata su una piattaforma può apparire diversa quando visualizzata su un'altra piattaforma.

Componenti e contenitori

Un'interfaccia utente grafica è costituita da elementi grafici chiamati componenti. I componenti tipici includono elementi come pulsanti, barre di scorrimento e campi di testo. I componenti consentono all'utente di interagire con il programma e forniscono all'utente un feedback visivo sullo stato del programma. Nell'AWT, tutti i componenti dell'interfaccia utente sono istanze della classe Component o di uno dei suoi sottotipi.

I componenti non sono isolati, ma piuttosto si trovano all'interno dei contenitori. I contenitori contengono e controllano il layout dei componenti. I contenitori sono essi stessi componenti e possono quindi essere collocati all'interno di altri contenitori. Nell'AWT, tutti i contenitori sono istanze della classe Container o di uno dei suoi sottotipi.

Spazialmente, i componenti devono adattarsi completamente al contenitore che li contiene. Questa nidificazione di componenti (compresi i contenitori) nei contenitori crea un albero di elementi, che inizia con il contenitore alla radice dell'albero e si espande fino alle foglie, che sono componenti come i pulsanti.

L'illustrazione nella Figura 1 mostra una semplice interfaccia utente grafica come apparirebbe se visualizzata in Windows 95. La Figura 2 mostra i componenti dell'interfaccia della Figura 1 disposti come un albero.

Tipi di componenti

La Figura 3 mostra la relazione di ereditarietà tra le classi dei componenti dell'interfaccia utente fornite da AWT. Componente di classe definisce l'interfaccia a cui devono aderire tutti i componenti.

L'AWT fornisce nove classi di componenti non container di base da cui è possibile costruire un'interfaccia utente. (Ovviamente, nuove classi di componenti possono essere derivate da uno qualsiasi di questi o dalla classe Component stessa.) Queste nove classi sono la classe Button, Canvas, Checkbox, Choice, Label, List, Scrollbar, TextArea e TextField. La Figura 4 mostra un'istanza di ogni classe.

È necessario un browser abilitato per Java per visualizzare questa applet.

Figura 4.

Nove componenti dell'interfaccia utente

La fonte per questa visualizzazione si trova qui.

Tipi di contenitori

L'AWT fornisce quattro classi container. Sono la classe Window ei suoi due sottotipi - la classe Frame e la classe Dialog - così come la classe Panel. Oltre ai contenitori forniti dall'AWT, la classe Applet è un contenitore: è un sottotipo della classe Panel e può quindi contenere componenti. Di seguito vengono fornite brevi descrizioni di ciascuna classe di container fornita da AWT.

Finestra Una superficie di visualizzazione di primo livello (una finestra). Un'istanza della classe Window non è collegata né incorporata in un altro contenitore. Un'istanza della classe Window non ha bordo né titolo.
Telaio Una superficie di visualizzazione di primo livello (una finestra) con un bordo e un titolo. Un'istanza della classe Frame può avere una barra dei menu. Per il resto è molto simile a un'istanza della classe Window.
Dialogo Una superficie di visualizzazione di primo livello (una finestra) con un bordo e un titolo. Un'istanza della classe Dialog non può esistere senza un'istanza associata della classe Frame.
Pannello

Un contenitore generico per contenere componenti. Un'istanza della classe Panel fornisce un contenitore a cui aggiungere componenti.

Creazione di un contenitore

Prima di aggiungere i componenti che compongono un'interfaccia utente, il programmatore deve creare un contenitore. Quando si crea un'applicazione, il programmatore deve prima creare un'istanza della classe Window o della classe Frame. Quando si crea un'applet, esiste già un frame (la finestra del browser). Poiché la classe Applet è un sottotipo della classe Panel, il programmatore può aggiungere i componenti all'istanza della classe Applet stessa.

Il codice nel listato 1 crea un frame vuoto. Il titolo del frame ("Esempio 1") è impostato nella chiamata al costruttore. Un frame è inizialmente invisibile e deve essere reso visibile invocando il suo show()metodo.

import java.awt. *;

public class Esempio1 {public static void main (String [] args) {Frame f = new Frame ("Example 1");

f.show (); }}

Listato 1.

Una cornice vuota

Il codice nel Listato 2 estende il codice del Listato 1 in modo che la nuova classe erediti dalla classe Panel. Nel main()metodo, viene creata un'istanza di questa nuova classe e aggiunta all'oggetto Frame tramite una chiamata al add()metodo. Il risultato viene quindi visualizzato. I risultati di entrambi gli esempi dovrebbero apparire identici (ovvero, dovrebbero sembrare piuttosto poco interessanti).

import java.awt. *;

public class Example1a estende Panel {public static void main (String [] args) {Frame f = new Frame ("Example 1a");

Esempio1a ex = nuovo Esempio1a ();

f.add ("Centro", ex);

f.pack (); f.show (); }}

Listato 2.

Una cornice con un pannello vuoto

Derivando la nuova classe dalla classe Applet invece della classe Panel, questo esempio può ora essere eseguito sia come applicazione autonoma che come applet incorporata in una pagina Web. Il codice per questo esempio è fornito nel Listato 3. L'applet risultante è visualizzato nella Figura 5 (ed è ancora abbastanza poco interessante).

import java.awt. *;

public class Example1b estende java.applet.Applet {public static void main (String [] args) {Frame f = new Frame ("Example 1b");

Esempio1b ex = nuovo Esempio1b ();

f.add ("Centro", ex);

f.pack (); f.show (); }}

Listato 3.

Un frame con un'applet vuota

È necessario un browser abilitato per Java per visualizzare questa applet.

Figura 5.

Una cornice vuota

Nota: un oggetto Window, e in alcuni casi anche un oggetto Dialog, potrebbe sostituire l'oggetto Frame. Sono tutti contenitori validi e i componenti vengono aggiunti a ciascuno nello stesso modo.

Aggiunta di componenti a un contenitore

Per essere utile, un'interfaccia utente deve essere composta da più di un semplice contenitore: deve contenere componenti. I componenti vengono aggiunti ai contenitori tramite il add()metodo di un contenitore . Esistono tre forme di base del add()metodo. Il metodo da utilizzare dipende dal layout manager del contenitore (vedere la sezione intitolata Layout dei componenti ).

Il codice nel Listato 4 aggiunge la creazione di due pulsanti al codice presentato nel Listato 3. La creazione viene eseguita nel init()metodo perché viene chiamata automaticamente durante l'inizializzazione dell'applet. Pertanto, indipendentemente da come viene avviato il programma, i pulsanti vengono creati, perché init()viene chiamato dal browser o dal main()metodo. La Figura 6 contiene l'applet risultante.

import java.awt. *;

la classe pubblica Esempio3 estende java.applet.Applet {public void init () {add (new Button ("One")); aggiungi (nuovo pulsante ("Due")); }

public Dimension preferredSize () {return new Dimension (200, 100); }

public static void main (String [] args) {Frame f = new Frame ("Esempio 3");

Esempio3 ex = nuovo Esempio3 ();

ex.init ();

f.add ("Centro", ex);

f.pack (); f.show (); }}

Listato 4.

Un'applet con due pulsanti

È necessario un browser abilitato per Java per visualizzare questa applet.

Figura 6.

Un'applet con due pulsanti

Layout dei componenti

Fino a questo punto non è stato detto nulla sulla disposizione dei componenti che sono stati aggiunti a un contenitore. Il layout è controllato non dal contenitore, ma da un gestore di layout associato al contenitore. Il gestore layout prende tutte le decisioni sul posizionamento dei componenti. Nell'AWT, tutte le classi di layout manager implementano l'interfaccia LayoutManager.

L'AWT fornisce cinque gestori di layout. Si va da molto semplice a molto complesso. Questo articolo copre solo le due classi di layout manager usate dagli esempi qui contenuti: la classe FlowLayout e la classe BorderLayout.

La classe FlowLayout inserisce i componenti in un contenitore da sinistra a destra. Quando lo spazio in una riga è esaurito, viene avviata un'altra riga. La versione a argomento singolo del add()metodo di un contenitore viene utilizzata per aggiungere componenti.

La classe BorderLayout ha cinque zone, come illustrato nella Figura 7. Le zone sono denominate "Nord", "Sud", "Est", "Ovest" e "Centro". Un singolo componente può essere posizionato in ciascuna di queste cinque zone. Quando il contenitore che lo racchiude viene ridimensionato, ogni zona del bordo viene ridimensionata quanto basta per contenere il componente posizionato all'interno. Lo spazio in eccesso viene assegnato alla zona centrale. La versione a due argomenti del add()metodo di un contenitore viene utilizzata per aggiungere componenti. Il primo argomento è un oggetto String che nomina la zona in cui posizionare il componente.

Ogni classe contenitore ha un gestore di layout predefinito. Il gestore di layout predefinito per la classe Frame e la classe Dialog è il gestore BorderLayout. Il gestore di layout predefinito per la classe Panel (e la classe Applet) è il gestore FlowLayout.

Il codice nel listato 5 utilizza entrambi i gestori di layout e include alcuni altri componenti dell'interfaccia utente. Il risultato è visualizzato nella Figura 8.

import java.awt. *;

la classe pubblica Example4 estende java.applet.Applet {public void init () {Panel p;

setLayout (new BorderLayout ());

p = nuovo pannello ();

p.add (new TextArea ());

aggiungi ("Centro", p);

p = nuovo pannello ();

p.add (nuovo pulsante ("Uno")); p.add (nuovo pulsante ("Due"));

Scelta c = nuova scelta ();

c.addItem ("uno"); c.addItem ("due"); c.addItem ("tre");

p.add (c);

aggiungi ("Sud", p); }

public static void main (String [] args) {Frame f = new Frame ("Esempio 4");

Esempio4 ex = nuovo Esempio4 ();

ex.init ();

f.add ("Centro", ex);

f.pack (); f.show (); }}

Listato 5.

Un esempio più complicato

È necessario un browser abilitato per Java per visualizzare questa applet.

Figura 8.

Un esempio più complicato

Gestione degli eventi

Gli esempi precedenti non fanno altro che visualizzare un'interfaccia utente inerte. È ovviamente molto importante che un'interfaccia utente agisca in seguito all'input dell'utente. Tuttavia, va oltre lo scopo di questo articolo approfondire i misteri della gestione degli eventi. Questo deve aspettare fino a un futuro articolo. Tuttavia, nell'interesse della completezza, il codice di esempio nel Listato 6 mostra come gestire un tipo di evento che un programma può ricevere. La nuova classe sovrascrive il action()metodo fornito dalla classe Component. Il action()metodo risponde agli eventi di azione generati, ad esempio, dalla selezione di un elemento da un elenco a comparsa. Ilaction()richiede che siano forniti due parametri, un'istanza Event e un'istanza Object. L'istanza Event contiene informazioni sull'evento, incluso il target dell'evento (il componente che per primo ha ricevuto l'evento), le coordinate xey dell'evento e l'ora in cui si è verificato l'evento. L'istanza Object contiene una parte di dati specifica dell'evento. Per gli oggetti Button contiene il testo nell'etichetta del pulsante.

import java.awt. *;

la classe pubblica Example5 estende java.applet.Applet {TextArea ta = null;

public void init () {Panel p;

setLayout (new BorderLayout ());

p = nuovo pannello ();

ta = new TextArea ();

p.add (ta);

aggiungi ("Centro", p);

p = nuovo pannello ();

p.add (nuovo pulsante ("Uno")); p.add (nuovo pulsante ("Due"));

Scelta c = nuova scelta ();

c.addItem ("uno"); c.addItem ("due"); c.addItem ("tre");

p.add (c);

aggiungi ("Sud", p); }

azione booleana pubblica (Evento e, Oggetto o) {String str = (String) o;

ta.appendText (str + "\ n");

return false; }

public static void main (String [] args) {Frame f = new Frame ("Esempio 5");

Esempio5 ex = nuovo Esempio5 ();

ex.init ();

f.add ("Centro", ex);

f.pack (); f.show (); }}

Listato 6.

Un esempio con la gestione degli eventi