MokaPackages
I packages del JDK
java.awt
di
Antonio
Cisternino
Un viaggio nella grafica di Java


 



 


In questo articolo viaggeremo attraverso le classi dell'AWT package originale per la grafica in Java. Non affronteremo invece le estensioni dell'AWT come ad esempio le Swing

Introduzione

È inutile dire che al package AWT andrebbero dedicate due o tremila puntate se si volesse in qualche modo dare anche una piccola spolverata sulle sue possibilità. In questa panoramica rinunceremo quindi alla completezza offrendo una visita ragionata delle principali classi del package lasciando a chi ne a voglia l'arduo compito di approfondire e, soprattutto, sperimentare!!!
L'AWT è stato uno dei package che ha decretato il successo di Java: per la prima volta infatti nella libreria standard di un linguaggio si trovava un'astrazione del concetto di interfaccia grafica. L'AWT sta infatti a Java come la libreria stdio.h sta al C. Se infatti i linguaggi precedenti avevano sempre scartato l'idea di standardizzare l'interfaccia grafica (lasciando il povero programmatore in preda a mari di librerie) la Sun introdusse l'AWT per consentire alle applet di aprire finestre sulla macchina client e offrire un'interfaccia grafica per l'utente.
Inoltre questo package è quello che più di altri rappresentato un argine tra la versione 1.0.2 di Java e la versione 1.1 poiché è ne è stato sconvolto l'impianto di base.
L'idea originale dell'AWT era quella di offrire una libreria che fosse multipiattaforma offrendo componenti grafici comuni a tutte le interfacce grafiche disponibili. Quindi le varie componenti come bottoni, liste, combobox, checkbox, radio button, caselle di testo e quanto altro sono controllabili da Java nello stesso modo sia su Windows, che su Unix che su Mac. Ad ogni componente offerto dall'interfaccia grafica nativa è associato un peer in Java (un oggetto che consente da Java la manipolazione dell'oggetto reale). Così troviamo classi come Button, TextField, etc. che sono solo dei rappresentanti Java dei peer dell'interfaccia grafica.
Nella sua prima implementazione l'AWT adottava una struttura simile ai framework di classi per l'interfaccia grafica come MFC o OWL. In un primo momento la gestione degli eventi veniva propagata attraverso la gerarchia delle classi (secondo la relazione di ereditarietà); successivamente fu adottato il delegation event model per alleggerire il costo della gestione dei messaggi e ottimizzare l'intero framework.
Questa panoramica coprirà i tre aspetti fondamentali della gestione dell'interfaccia: la gestione degli eventi, la gestione dei componenti, la gestione delle finestre e il layout dei componenti.

La struttura generale del package AWT
Il package AWT contiene svariati sottopackage che sono cresciuti al succedersi delle nuove funzioni. In particolare troviamo i seguenti package nella versione 1.2 di Java:

    java.awt.color
    java.awt.datatransfer
    java.awt.dnd
    java.awt.event
    java.awt.font
    java.awt.geom
    java.awt.im
    java.awt.image
    java.awt.image.renderable
    java.awt.print
Il package java.awt.color contiene classi per la gestione avanzata del color space. Il package java.awt.datatransfer definisce le classi necessarie per il trasferimento dei dati dall'applicazione Java ad altre applicazioni, possibilmente anche non Java. Questo trasferimento di dati può esprimersi tramite il passaggio di dati nella clipboard di sistema oppure tramite l'azione di drag and drop. La clipboard può essere gestita direttamente con questo package mentre il drag and drop è gestito dal package java.awt.dnd. Il package java.awt.event offre il supporto per la gestione degli eventi come vedremo in seguito. Il package java.awt.font contiene interfacce e classi per il trattamento avanzato delle fonti; contiene ad esempio l'utilissima classe LineBreakMeasurer che spezza una stringa in più stringhe in modo tale che una linea di testo occupi una certa larghezza dato il font usato per realizzarla. Il package java.awt.geom offre varie classi ed interfacce per la gestione della grafica 2D fornendo la possibilità anche di disegnare curve come le classi QuadCurve2D.Double e QuadCurve2D.Float. Il package java.awt.im si occupa di offrire un'interfaccia per la gestione dell'input per la realizzazione di editor consentendo l'immissione di caratteri che non siano quelli occidentali (Kanji, ideogrammi...). I package java.awt.image e java.awt.image.renderable offrono il supporto per la manipolazione delle immagini. Non abbiamo sufficiente spazio per descrivere questi due package che offrono tra l'altro il supporto per il filtering delle immagini e la loro generazione. Infine il package java.awt.print offre il supporto per stampare documenti usando Java.
Nel seguito di questo appuntamento ci concentreremo sul package java.awt trascurando gli altri package eccezion fatta per il package java.awt.event indispensabile per gestire gli eventi dell'interfaccia grafica.
 
 
 

Gli eventi in AWT
Come abbiamo già accennato nell'introduzione la gestione degli eventi è un aspetto cruciale nella gestione dell'interfaccia grafica. Il sistema di gestione degli eventi ha subito una profonda trasformazione dalla sua prima versione per migliorare l'efficienza della grafica in Java.
Noi ci concentreremo quindi sul nuovo modello di gestione degli eventi chiamato delegation event model. Questo modello prevede che ogni componente tenga una lista di oggetti ascoltatori degli eventi che lui è in grado di produrre. Nel momento in cui si produce l'evento il componente in questione invoca un metodo che identifica l'evento per ogni oggetto ascoltatore. Quindi che è interessato a ricevere gli eventi da un oggetto si deve registrare presso quell'oggetto essendo un ascoltatore per gli eventi emessi. Essere un ascoltatore significa implementare una precisa interfaccia Java.
Il package java.awt.event definisce tutte le interfacce per gli ascoltatori di tutti gli eventi lanciati dai componenti dell'AWT. 
Le principali sono:
 
ActionListener L'interfaccia per ricevere gli eventi collegati alle azioni.
AdjustmentListener L'interfaccia per ascoltare gli eventi di cambiamento di un valore
ComponentListener L'interfaccia per ricevere gli eventi dei componenti
ContainerListener L'interfaccia per ascoltare gli eventi dei contenitori
FocusListener L'interfaccia per sapere quando un componente ha il fuoco della tastiera.
ItemListener L'interfaccia per selezionare gli oggetti.
KeyListener L'interfaccia che permette di ascoltare gli eventi che provengono dalla tastiera.
MouseListener L'interfaccia che consente di ascoltare gli eventi principali del mouse: quando entra, esce da un componente o quando viene premuto il bottone.
MouseMotionListener L'interfaccia che riceve gli eventi corrispondenti al movimento del mouse.
TextListener L'interfaccia che consente di capire quando è cambiato il contenuto di una casella di testo.
WindowListener L'interfaccia per ricevere gli eventi lanciati da una finestra.

Come esempio consideriamo la gestione della pressione di un bottone: 

 
/** Classe che gestirà l'evento. */
class ButtonHandler implements ActionListerner {
  void actionPerformed(ActionEvent e) {
    System.out.println("Bottone "+getActionCommand());
  }
}

// Codice che registra l'ascoltatore presso il bottone
...
Button b = new Button("Prova");
b.addActionListener(new ButtonHandler());
...
 
 

Poiché molte interfacce hanno molti metodi da implementare il package java.awt.event offre anche degli Adapter ovvero delle classi che implementano le interfacce degli ascoltatori offrendo una gestione di default agli eventi. In questo modo è possibile estendere una classe da un Adapter e ridefinire solo i metodi corrispondenti agli eventi che si vogliono gestire.
Gestire i componenti
La gestione dei componenti è semplice nell'AWT: si crea un oggetto istanziando una classe e lo si aggiunge ad un contenitore che lo ospiterà visualizzandolo. I componenti più importanti presenti nel package sono:
 
Button Classe associata ai bottoni dell'interfaccia grafica.
Canvas Componente base per creare i propri componenti.
Checkbox Casella spuntabile con testo associato.
Label È un'etichetta di testo.
List Lista di elementi.
Scrollbar Barra di scorrimento (può essere orizzontale o verticale).
TextArea Casella di testo multilinea.
TextField Casella di testo a linea singola.

Ognuno di questi componenti può essere istanziato (passando gli opportuni parametri al costruttore), possono essere aggiunti gli ascoltatori di eventi, ed infine può essere visualizzato. Tutte le classi elencate sono derivate dalla classe base Component che astrae il concetto di componente. Questi componenti sono opachi nel senso che coprono completamente l'area su cui risiedono eventualmente con un colore di background. Con l'avvento del JDK1.1 sono stati introdotti i cosiddetti lightweight components ovvero i componenti leggeri. Questi si caratterizzano perchè non viene allocata una finestra per loro (come avviene invece nel caso di componenti definiti a partire da un Canvas) e quindi possono assumere qualsiasi forma senza essere costretti ad assumere la classica forma rettangolare. Un componente lightweight si ottiene semplicemente estendendo la classe Component piuttosto che la classe Canvas. 
I contenitori, le finestre e i layout
I componenti sono inseriti in contenitori che si occupano di organizzarli graficamente secondo il LayoutManager correntemente impostato.
I contenitori di più alto livello sono le finestre (Frame, Dialog, Window, ...).
una delle trovate più geniali dell'AWT è stata sicuramente l'introduzione del componente Panel che è sia un componente (come un bottone, una casella di testo, etc.) che un contenitore di componenti (come una finestra). La forza di questa trovata è che i pannelli possono essere "incastonati" uno dentro l'altro ottenendo dei layout dei componenti anche molto sofisticati.
Poiché le prime versioni di Java non disponevano di ambienti di sviluppo grafici i programmatori della Sun si ingegnarono e risolsero il problema della disposizione dei componenti in una finestra in un modo a dir poco geniale che spesso passa ingiustamente in sordina. La soluzione proposta è secondo me un capolavoro di concettualizzazione per una strutturazione ad oggetti della libreria.
Ogni contenitore ha associato un oggetto che è un LayoutManager ovvero un oggetto che implementa l'interfaccia omonima. Questo oggetto è investito del compito di disporre i componenti all'interno del contenitore secondo una politica. Inoltre, quando si rende necessario, questo oggetto dovrà ricalcolare la disposizione dei componenti.
Nel package java.awt sono distribuiti vari layout manager che adottano differenti politiche nella disposizione dei componenti. Troviamo ad esempio il BorderLayout che in grado di disporre di al più cinque componenti; oppure il complesso ma potentissimo GridBagLayout.
La rivoluzionarietà di questa strutturazione concettuale è legata al fatto che la disposizione dei componenti non dipende più dai pixel come spesso accade nelle interfacce grafiche ma da specifiche che non dipendono dalla dimensione del contenitore. Questo è possibile al prezzo di un sacrificio della completa generalità nella disposizione dei componenti. D'altronde la possibilità di incastrare i pannelli uno dentro l'altro consente di usare differenti layout all'interno di uno stesso contenitore.
Due metodi della classe Component che rivestono un ruolo chiave nel funzionamento dei layout manager sono il metodo getMinimumSize() e il metodo getPreferredSize(): spesso i layout manager sfruttano queste indicazioni fornite da un componente per decidere l'effettiva disposizione dei componenti all'interno di un contenitore. 
 
 
 

Conclusioni
Fare una panoramica sul package AWT non è cosa facile e spero di esservi riuscito (almeno un pochino). Questo perché è la libreria più vasta e complessa di Java (dopo Swing che è costruita sopra di essa) che sicuramente ne ha decretato il successo.
Non esistono inoltre esempi tipo che non scadano nel banale. Per cui mi sembrava più corretto cercare di dare una visione coerente del package piuttosto che una serie di esempi del suo uso.


MokaByte rivista web su Java

MokaByte ricerca nuovi collaboratori

Chi volesse mettersi in contatto con noi può farlo scrivendo a mokainfo@mokabyte.it