Semplice tutorial sulla gestione di interfacce grafiche con Swing di Java.

(a cura di Malaspina Maurizio mauxxx@libero.it)

Introduzione

Questo mini tutorial è dedicato a tutti coloro che si affacciano per la prima volta al linguaggio Java o che non hanno mai ancora avuto nulla a che fare con le interfacce grafiche pur conoscendo il linguaggio in oggetto.

Cercherò di elencare i passi indispensabili per costruire GUI (Graphics User Interface) utilizzando tutti gli elementi di Swing che fanno parte del package javax.swing premettendo che non si tratta dell'unico tool esistente adatto allo scopo (si veda AWT : Abstract Windowing Toolkit), ma di un efficiente standard rilasciato da Sun, completamente scritto in Java, in modo da assicurarne un perfetto porting interpiattaforma.

Creare una semplice finestra

Per utilizzare una classe Swing occorre importarla singolarmente (istruzione import) oppure importare tutte le classi come segue :

import javax.swing.*; // rende accessibili tutte le classi Swing

(Poiché le classi Swing ereditano delle proprietà dalle stesse superclassi di AWT, quindi è possibile utilizzare contemporaneamente componenti di AWT e Swing. E' comunque consigliato limitarsi all'uso di Swing.)

Il primo passo consiste nella creazione di una classe contenitore che rappresenta l'interfaccia utente grafica sulla quale potranno essere posizionati componenti interattivi come pulsanti, caselle di testo e tutto ciò messo a disposizione da tali classi.

Ci sono due oggetti principali dai quali poter ereditare le funzionalità di interfaccia :

Utilizzeremo in questa trattazione soltanto la classe Jframe come superclasse dalla quale erediteremo le caratteristiche volute nelle nostre GUI.

Vediamo quali sono i passi essenziali per creare una semplice finestra di base sulla quale andremo a piazzare dei semplici componenti :

  1. Rendere la nostra interfaccia una sottoclasse di Jframe

  2. inizializzarla invocando un opportuno metodo costruttore

  3. impostarne le dimensioni esprimendole in pixel

  4. associare un evento alla chiusura della finestra

  5. visualizzare il frame!

Beh... a volte vale molto più un vecchio sano codice che mille parole :

import javax.swing.*;

public class NostroFrame extends JFrame { // Creiamo una sottoclasse di Jframe


public NostroFrame() { // definiamone un costruttore

super("Titolo del frame"); // richiama il costruttore della superclasse Jframe passando come parametro la stringa da visualizzare sulla barra del titolo

setSize(500,300); // impostiamo le dimensioni del frame LARGHEZZA , ALTEZZA in pixel

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // associamo l'evento di chiusura al solito bottone di chiusura

setVisible(true); // rendiamo il frame visibile dato che per default non lo è!

}


public static void main(String argv[]) {

NostroFrame nf = new NostroFrame(); // Creiamo un'istanza del nostro frame

}



Ecco l'output del programma :






Non abbiamo bisogno di dire altro tranne due specifiche sui parametri dei metodi utilizzati :

setDefaultCloseOperation(JFrame.FLAG);

questo metodo permette di modificare l'azione di default di Java di continuare ad eseguire l'applicazione che ha generato il frame anche dopo aver clickato sull'apposito bottone di chiusura del frame ; segue un elenco del significato del campo flag :

EXIT_ON_CLOSE : terminazione del programma quando il frame viene chiuso

DISPOSE_ON_CLOSE : chiude e libera il solo oggetto frame, il processo continua

DO_NOTHING_ON_CLOSE : mantiene aperto il frame e continua il processo (ignoriamo l'evento)

HIDE_ON_CLOSE : chiude il frame e continua l'esecuzione

Due parole sui metodi per visualizzare o nascondere i frames :

show() oppure setVisible(true) per rendere visibile il frame che come abbiamo detto non lo è per default

hide() oppure setVisible(false) ovviamente per nasconderlo

per scegliere la posizione iniziale si può utilizzare il metodo setBounds(int, int, int, int); con argomenti da nell'ordine di digitazione x ed y dell'angolo superiore sinistro e dimensioni larghezza ed altezza del frame.

E' arrivato il momento di aggiungere componenti ad un frame.

Inserimento di componenti nel frame

I componenti ad esempio i bottoni, vanno inseriti in un pannello dopo essere stati creati ed opportunamente inizializzati, occorre poi far diventare tale pannello il riquadro del contenuto del frame .

I componenti non sono altro che istanze di classi del componente stesso ed i pannelli sono divisi in “pane” una sorta di contenitori annidati con il riquadro del contenuto detto “content pane”.

Ragioniamo sul sorgente :

import javax.swing.*;


public class Pulsanti extends JFrame {

JButton pulsanteUno = new JButton("Pulsante uno"); // Creazione dei pulsanti

JButton pulsanteDue = new JButton("Pulsante due");

public Pulsanti() {

super("Prova pulsanti");

setSize(300, 80);

setDefaultCloseOperation(EXIT_ON_CLOSE);

JPanel pannello = new Jpanel(); // Creazione del pannello che conterrà i pulsanti

pannello.add(pulsanteUno); // Aggiunta dei pulsanti al pannello

pannello.add(pulsanteDue);

setContentPane(pannello); // Trasforma il pannello nel contenuto del frame

show(); // Visualizza l'intero frame

}


public static void main(String argv[]) {

Pulsanti p = new Pulsanti();

}

}

Ecco l'output del programma :




Se al posto delle semplici scritte vogliamo aggiungere grafica ai pulsanti dobbiamo utilizzare uggetti di tipo ImageIcon da incorporare nei bottoni stessi :



ImageIcon img = new ImageIcon("c:\\documenti\\swing\\image1.gif"); // legge il file .gif e lo incorpora nell'ooggetto img

JButton pulsanteUno = new Jbutton(img); // Passo img al costruttore del pulsante

Naturalmente è possibile attivare o disattivare componenti, renderli visibili o meno :

setEnabled(boolean) e isEnabled()

setVisible(boolean) e isVisible()

o ridimensionare pulsanti : setSize(int, int) o setSize(Dimension) e Dimension getSize()

Descriverò il funzionamento basilare di Etichette, campi di testo e aree di testo, elementi indispensabili per rendere la nostra applicazione interattiva ed operante su dati inseriti dall'utente :

I costruttori di base sono :

  1. JLabel(String); // Crea un'etichetta visualizzante la stringa passata come parametro

  2. JLabel(String, int); // Crea un'etichetta visualizzante la stringa passata come parametro definendone l'allineamento a mezzo di un flag

  3. JLabel(String, Icon, int); // Crea un'etichetta visualizzante la stringa passata come parametro e l'icona associata definendone l'allineamento a mezzo di un flag

I tre flag che definiscono l'allineamento sono : SwingConstants.LEFT SwingConstants.RIGHT SwingConstants.CENTER , quest'ultimo può essere omesso poiché corrisponde al comportamento di default.

  1. JtextField(); // Genera un campo di testo vuoto

  2. JtextField(int); // Genera un campo di testo di larghezza specificata

  3. JtextField(String, int); // Genera un campo di testo contenente una stringa e di larghezza specificata

segue una lista dei metodi indispensabili per l'utilizzo :

  1. setEditable(boolean); // posto a “true” permette la modifica del testo contenuto, al contrario “false” non permette l'immissione di input da tastiera

  2. boolean isEditable(); // restituisce lo stato di modifica del componente

  3. setText(String); // permette di immettere testo nel componente

  4. String getText(); // restituisce ovviamente il contenuto in forma di stringa

  5. String getSelectedText(); // restituisce il solo testo selezionato dall'utente

    Una utile classe è il campo password con la capacità di crittare l'output a video con un carattere a nostra scelta durante la digitazione.

    Si tratta della classe JpasswordField che permette di creare un campo ad hoc per lo scopo definendone le dimensioni e mediante un opportuno metodo impostare il carattere per l'echo a video :

    JpasswordField pf = new JpasswordField(10); // istanzia un oggetto campo password di dimensione 10

    pf.setEchoChar('*'); // il classico asterisco!

I costruttori sono :

  1. JTextArea(int, int); // Crea un'area di testo di dimensioni righe, colonne

  2. JtextArea(String, int ,int); // Come sopra solo che inserisce una stringa da codice

I metodi sono getText(); getSelectedText() e setText(String) funzionanti come per i campi di testo ed alcune funzionalità di editing come :

append(String); // accoda del testo

insert(String, int); // inserisce del testo alla posizione specificata

setLineWrap( boolean); // specifica se “true” di andare a capo automaticamente a fine riga

setWrapStyleWord( boolean ); // va a capo con la parola se “true” o col singolo carattere se “false”

Corredo il tutto con il solito esempio :

/************************************************************************************************************************/

/* SEMPLICE UTILIZZO DI ETICHETTE, CAMPI ED AREE DI TESTO MEDIANTE USO DI SWING *****/

/***********************************************************************************************************************/


import javax.swing.*;


public class EtichetteEcampi extends JFrame {

JLabel etichetta1 = new JLabel("Allineamento a sinistraaaaaaaaaaaaaaaaaaa ", SwingConstants.LEFT);

JLabel etichetta2 = new JLabel("Allineamento al centro");

JLabel etichetta3 = new JLabel("Allineamento a destraaaaaaaaaaaaaa ", SwingConstants.RIGHT);

JTextField campoDiTesto = new JTextField("Immetti qui una stringa...",30);

JTextArea areaDiTesto = new JTextArea("Questa é un'area di testo di\n5 righe e 30 colonne",5,30);


public EtichetteEcampi() {

super("Etichette e campi");

Output del codice Etichette e campi di testosetSize(350, 300);

setDefaultCloseOperation(EXIT_ON_CLOSE);

JPanel pannello = new JPanel();

// impostiamo le proprietà dei componenti

campoDiTesto.setEditable(true);

areaDiTesto.setLineWrap(true);

areaDiTesto.setWrapStyleWord(true);

// ora aggiungiamo i componenti al pannello

pannello.add(etichetta1);

pannello.add(etichetta2);

pannello.add(etichetta3);

pannello.add(campoDiTesto);

pannello.add(areaDiTesto);

// rendiamo il pannello parte del nostro frame

setContentPane(pannello);

// Visualizziamo il tutto!

show();

}


public static void main(String argv[]) {

EtichetteEcampi ec = new EtichetteEcampi();

}

public static void main(String argv[]) {

EtichetteEcampi ec = new EtichetteEcampi();

}




Rimando i lettori interassati all'utilizzo di ulteriori controlli, come caselle combinate, elenchi a scorrimento, bottoni di scelta multipla, barre di scorrimento e di avanzamento, alla documentazione ufficiale di Java fornita dalla SUN ed alla consultazione della guida dei più familiari tool di sviluppo come ad esempio Borland Jbuilder Personal 7.0 disponibile gratuitamente per studenti (naturalmente non a scopi commerciali).Intraprendo tale scelta poiché ritengo che a fini implementatvi riguardanti semplici applicazioni distribuite, non si abbia bisogno di molto altro.Do un suggerimento per chi volesse includere una barra degli strumenti con dei pulsanti : fate riferimento alla classe JToolBar(int).

Avrete sicuramente notato che provando a ridimensionare il frame si ottengono spiacevoli side effect che si manifestano con la perdita di ordine dei nostri componenti all'interno del pannello.

Per ovviare a tale inconveniente dobbiamo imparare a gestire i layout per avere un controllo sulla loro collocazione spaziale.

Layout a griglia avanzata

Se siete entrati nella mentalità OOP di Java, potrete apprendere semplicemente tale concetto dall'esperienza sopra acquisita ; abbiamo visto che i frame per contenere componenti hanno bisogno di un oggetto di supporto, una sorta di gestore incapsulato detto pannello, all'interno del quale vengono inglobati i controlli come in una sorta di matrioska; similmente per gestire il layout abbiamo bisogno di definire ed inglobare un gestore del layout che contenga i componenti da piazzare e che aggrapperemo al frame.

In questo mini tutorial dirò, solo per completezza, che Java dispone di 5 layout che possono essere concatenati ed usati in maniera innestata limitandomi a spiegare solo l'iutilizzo di quello che ritengo il più versatile ed adatto ai più comuni scopi : il layout a griglia avanzata GridBagLayout.

Si tratta in linea di principio di suddividere un pannello in una griglia (righe e colonne), le cui celle saranno in grado di ospitare i componenti desiderati ; la peculiarità di questo metodo consiste nel fatto che un componente può occupare più di una cella della griglia (N.B. Una cella non può contenere più di un componente) , le proporzioni tra le dimensioni di riga e di colonna possono essere differenti ed i componenti possono assumere orientamenti diversi all'interno delle celle.

Bisogna prima di tutto stabilire il mappaggio delle celle all'interno del pannello, la notazione è quella classica (N° colonna, n° riga) a partire dall'angolo in alto a sinistra della griglia :

( 0 , 0 )

( 1 , 0 )

( 2 , 0 )

( 0 , 1 )

( 1 , 1 )

( 2 , 1 )

( 0 , 2 )

( 1 , 2 )

( 3 , 1 )



Ora bisognerà dividere il progetto del layout in 3 fasi :

  1. Creazione di un gestore di layout (classi GridBagLayout e GridBagConstrait)

  2. Definizione dei vincoli di ciascun componente

  3. comunicare i vincoli al punto 2 al gestore ed aggiungere quest'ultimo al contenitore

La calsse GridBagLayout è capace di istanziare il vero e proprio gestore di tutta la matrice ed è proprio una sua istanza che verrà agganciata al nostro panello, la classe GridBagConstrait invece si occupa di definire le regole di layout inerenti alle singole celle ; essa si avvale di 6 variabili di tipo int :

  1. gridx : n° di colonna della cella da riferire

  2. gridy : n° di riga della cella da riferire

  3. gridwidth : n° di colonne occupate dal componente (si considera sempre l'espansione del componente verso destra)

  4. gridheight : n° di righe occupate dal componente ( si considera l'espansione del componente verso il basso)

  5. weightx : definisce le proporzioni delle colonne

  6. weighty : definisce le proporzioni delle righe

I parametri dei punti 5 e 6 sono da considerarsi dei pesi ponderati. Per comprendere il concetto occorre rendersi conto che per fissare le ampiezze di una colonna basta fissare l'ampiezza di una cella della colonna stessa e per fissare l'altezza di una riga basta fissare l'altezza di una cella della riga stessa, le altre celle si adatteranno espandendosi all'area disponibile restante.

Per pesi ponderati intendo che se abbiamo una griglia 2 x 2 e vogliamo che l'ampiezza della prima cella sia il 30% dell'ampiezza della seconda, devo impostare weightx della cella (0,0) a 30 e weightx della cella (1,0) a 100, gli stessi valori delle celle sottostanti relativi allo stesso campo weightx posso lasciarli a 0 il che sta a significare che il layout per quella cella è stato definito altrove (nel nostro caso sulle celle soprastanti).

In definitiva si fa una somma dei parametri passati a tutte le celle di una riga o di una colonna e si applicano delle proporzioni con l'unica eccezione che uno 0 non vuol dire ampiezza o altezza nulla se in qualche altra parte ne è stato definito il layout.

Un trucchetto per scrivere velocemente codice può essere quello di fare in modo che le celle che definiscono il layout abbiano la somma dei valori dei campi pari a 100, così basterà limitarsi a scrivere il valore percentuale della larghezza dell'intero pannello o della sua altezza ; questo è il metodo che useremo negli esempi.

Si potrebbe pensare inoltre di inserire inizialmente solo pulsanti a posto dei componenti reali per via della loro semplicità gestionale e per la loro proprietà di riempire l'intera area ; in seguito si potranno sostituire semplicemente i componenti con quelli reali.

Rimangono da trattare solo due attributi per avere una gestione soddisfacente di questo layout dinamico e sono contenuti all'interno della classe GridBagConstraints :

    limit : definisce il tipo di espansione del componente all'interno della cella che può essere di 4 tipi

  1. GridBagConstraints.BOTH : espande in entrambe le direzioni (default)

  2. GridBagConstraints.NONE : nessuna espansione

  3. GridBagConstraints.HORIZONTAL : solo espansione orizzontale

  4. GridBagConstraints.VERTICAL : solo espansione verticale

    anchor : definisce l'orientazione del componente all'interno della cella , si hanno intuitivamente 8 costanti : GridBagConstraints.XYZdove al posto di XYZ sono possibili i seguenti : NORTH , NORTHEAST, EAST, SOUTHEAST, SOUTH, SOUTHWEST, WEST, NORTHWEST.

Penso che a questo punto solo un bel sorgente ci potrà illuminare riguardo questi meccanismi :

/***********************************************************************************************************/

/* GESTIONE DI UN LAYOUT A GRIGLIA AVANZATA MEDIANTE USO DI SWING ****/

/***********************************************************************************************************/

import javax.swing.*;

import java.awt.*;

public class Layout extends JFrame {

//Creiamo i componenti

JLabel ipLabel = new JLabel("IP host", SwingConstants.LEFT);

JLabel passwordLabel = new JLabel("Password", SwingConstants.LEFT);

JLabel fileDaInviareLabel = new JLabel("File da inviare", SwingConstants.LEFT);

JTextField ipText = new JTextField();

JPasswordField passwordText = new JPasswordField();

JTextField fileDaInviareText = new JTextField();

JButton pulsante = new JButton("Inizia TX");

// Definiamo un metodo che ci servirà per definire i limiti di layout

void impostaLimite(GridBagConstraints gbc, int gx, int gy, int gw, int gh, int wx, int wy) {

gbc.gridx = gx;

gbc.gridy = gy;

gbc.gridwidth = gw;

gbc.gridheight = gh;

gbc.weightx = wx;

gbc.weighty = wy;

}





public Layout() { // Il costruttore della nostra classe

super("File transfer appz");

setSize(300, 120);

setDefaultCloseOperation(EXIT_ON_CLOSE);

JPanel pannello = new JPanel();

// impostiamo le proprietà dei componenti

ipText.setEditable(true);

fileDaInviareText.setEditable(true);

passwordText.setEchoChar('*');

//definiamo il gestore di layout

GridBagLayout grigliaAvanzata = new GridBagLayout();

GridBagConstraints limite = new GridBagConstraints();

pannello.setLayout(grigliaAvanzata);

//definiamo i limiti di ogni componente e lo aggiungiamo al pannello

impostaLimite(limite,0,0,1,1,35,0); //etichetta IP host

limite.fill = GridBagConstraints.NONE;

limite.anchor = GridBagConstraints.EAST;

grigliaAvanzata.setConstraints(ipLabel,limite);

pannello.add(ipLabel);

impostaLimite(limite,1,0,1,1,65,100); //campo IP host

limite.fill = GridBagConstraints.HORIZONTAL;

grigliaAvanzata.setConstraints(ipText,limite);

pannello.add(ipText);

impostaLimite(limite,0,1,1,1,0,0); //etichetta password

limite.fill = GridBagConstraints.NONE;

limite.anchor = GridBagConstraints.EAST;

grigliaAvanzata.setConstraints(passwordLabel,limite);

pannello.add(passwordLabel);

impostaLimite(limite,1,1,1,1,0,100); //campo password

limite.fill = GridBagConstraints.HORIZONTAL;

grigliaAvanzata.setConstraints(passwordText,limite);

pannello.add(passwordText);

impostaLimite(limite,0,2,1,1,0,0); //etichetta File da inviare

limite.fill = GridBagConstraints.NONE;

limite.anchor = GridBagConstraints.EAST;

grigliaAvanzata.setConstraints(fileDaInviareLabel,limite);

pannello.add(fileDaInviareLabel);

impostaLimite(limite,1,2,1,1,0,100); //campo File da inviare

limite.fill = GridBagConstraints.HORIZONTAL;

grigliaAvanzata.setConstraints(fileDaInviareText,limite);

pannello.add(fileDaInviareText);

impostaLimite(limite,0,3,2,1,0,50); // Pulsante

limite.fill = GridBagConstraints.NONE;

limite.anchor = GridBagConstraints.CENTER;

grigliaAvanzata.setConstraints(pulsante,limite);

pannello.add(pulsante);

setContentPane(pannello); // rendiamo il pannello parte del nostro frame

show(); // Visualizziamo il tutto!

}



public static void main(String argv[]) {

Layout nf = new Layout();

}

}



Ecco infine l'output del programma :







Non resta che provare a gestire un layout differente!

Abbiamo notato che ora la nostra GUI è a prova di ridimensionamento ma non è il massimo dell'interattività, infatti cliccando sul pulsante non succede nulla.

Dobbiamo imparare ad utilizzare i componenti visualizzati ed è per questo che bisogna parlare di eventi :

Gestione degli eventi

Tutto ciò che accade nella nostra interfaccia è interpretato come un evento, dobbiamo imparare a gestire e classificare gli eventi, utilizzando una serie di classi dette ascoltatori di eventi. Per utilizzarle, in Java 2, è necessario implementare un'interfaccia ascoltatore di eventi, tenendo presente che quando una classe implementa un'interfaccia deve occuparsi di definirne tutti i metodi.

Importando il package java.awt.event (import java.awt.event.* ) si rendono disponibili i seguenti ascoltatori di metodi :

Per usare tali ascoltatori di eventi è necessario creare un componente, creare un ascoltatore di eventi ed associarglielo prima di impostare le altre proprietà del componente ed infine includerlo in un pannello ; si noti che la cronologia di tale sequenza è determinante ai fini della corretta implementazione.

Segue la lista dei metodi che sono implementati nelle classi dei componenti che li possono utilizzare (in base alla lista sopra) nello stesso ordine della lista dei gestori di evento :

ecco come associare un ascoltatore di eventi di tipo ActionListener ad un pulsante :

Jbutton pulsante = new Jbutton(“Pulsante attivo”);

pulsante.addActionListener(this);

si noti che tutti i metodi che istanziano un ascoltatore di eventi richiedono un oggetto come parametro, tale oggetto deve essere un'istanza di una classe che implementi una corretta interfaccia ascoltatore, in questo caso la nostra classe dato che gestiremo dal suo interno gli eventi andandoci a definire i metodi dell'interfaccia che verranno richiamati ed eseguiti automaticamente in seguito al verificarsi di ogni evento predisposto per essere gestito (di cui abbiamo istanziato un'oggetto ascoltatore di eventi all'interno di almeno un componente della nostra interfaccia utente).

Vediamo ora come utilizzare gli ascoltatori di eventi nel caso di “eventi di azione”.

Se nella GUI sono presenti più di un componente reso interattivo, dobbiamo occuparci del riconoscimento di quale di essi ha generato l'evento prima di intraprendere un'azione, ad esempio se abbiamo due pulsanti ai quali corrispondono due diversi comandi, ci si deve incaricare di intercettare quale sia stato il pulsante premuto e richiamare la relativa routine associata ; a tale scopo ci viene incontro il metodo getSource(), che ci rilvelerà informazioni riguardo la natura del componente che ha segnalato di essere gestito.

Tale metodo dovrà essere invocato dall'oggetto che viebe automaticamente passato come parametro alla/e funzione/i dell'interfaccia che dobbiamo implementare (di tipo EventObject).

L'interfaccia actionListener ha un solo evento : actionPerformed(), quindi dovremo implementare solo il suo codice.

Esempio di due pulsanti :

public void actionPerformed(ActionEvent evt){

// gestiamo l'evento

Object src = evt.getSource(); // individuiamo il mittente della segnalazione

if (src == pulsante1) funzionePulsante1(); // scegliamo il giusto gestore dell'evento

else if (src == pulsante2) funzionePulsante2();

}

Se ad esempio abbiamo due componenti di diversa natura, ad esempio un pulsante ed un campo di testo che sono entrambi in grado di generare un evento “in azione”, il seguente codice può esserci utile ad intercettare il mittente della segnalazione :

public void actionPerformed(ActionEvent evt){

// gestiamo l'evento

Object src = evt.getSource(); // individuiamo il mittente della segnalazione

if (src istanceof JtextField) funzioneCampoDiTesto(); // scegliamo il giusto gestore dell'evento

else if (src istance of JButton) funzionePulsante();

}

Un ulteriore modo di intercettare il segnalante è quello di utilizzare il metodo getActionCommand() che ritorna informazioni riguardo il componenente, informazioni sotto forma di stringa che possono essere impostate con setActionCommand(String) . Tale metodo risulta eccezionalmente utilie nel caso più di un componente deve effettuare la stessa funzione.

Per quanto riguarda gli eventi di selezione (focus) che si manifestano quando un componente ottiene o perde lo stato di elemento attivo, gli unici metodi che occorre implementare sono :

public void focusGained(FocusEvent evt) e public void focusLost(FocusEvent evt) e gestire il tutto come visto sopra.

Glie venti di elemento devono essere implementati sviluppando il metodo void itemStateChanged(ItemEvent evt) e per determinare l'oggetto che lo ha invocato occorre invocare getItem() sull'oggetto ItemEvent ; si può anche controllare se l'elemento è stato selezionato o deselezionato richiamando getStateChange() che ritorna due costanti : ItemEvent.DESELECTED o ItemEvent.SELECTED.

Gli eventi della tastiera vanno gestiti implementando le seguenti :

public void keyPressed(KeyEvent evt)

public void KeyReleased(KeyEvent evt)

public void KeyTyped(KeyEvent evt)

il metodo getKeyChar() dell'oggetto KeyEvent restituisce il codice del carattere del tasto associato all'evento e se non eseste un carattere UNICODE da associargli, ritorna la costante KeyEvent.CHAR_UNDEFINED.

Per quanto riguarda gli eventi del mouse, che sono generati da componenti che interagiscono col puntatore del mouse, occorre gestire i seguenti metodi :

mouseClicked(MouseEvent);

mouseEntered(MouseEvent);

mouseExited(MouseEvent);

mousePressed(MouseEvent);

mouseReleased(MouseEvent);

ogniuno del tipo public void.

Associate alla classe Mouse Event le seguenti funzioni : getClickCount() che ritorna il n° di click effettuati su un componente, getPoint() che ritorna le coordinate, a mezzo di un oggetto di tipo Point, del componente sopra il quale è stato effettuato il click del mouse, getX() e getY() che restituiscono le rispettive posizioni.

Se si vuole intercettare il passaggio del puntatore del mouse sopra un componente ci si deve servire dell'interfaccia MouseMotionListener che implementa i seguenti metodi : mouseDragged(MouseEvent evt) e mouseMoved(MouseEvent evt) ; con gli argomenti di tali funzioni è possibile richiamare i metodi sopra detti.

Per gestire gli eventi di finestra che si manifestano quando un utente apre o chiude una JWindow o un Jframe, si devono utilizzare i seguenti metodi :

windowActivated(WindowEvent)

windowClosed(WindowEvent) // dopo che la finestra è stata chiusa

windowClosing(WindowEvent) // al momento di chiusura della finestra

windowDeactivated(WindowEvent)

windowDeiconified(WindowEvent)

windowIconified(WindowEvent)

windowOpened(WindowEvent)

ad esempio con windowClosing si può impedire la chiusura di una finestra.

Anche la classe WindowAdapter implementa l'interfaccia windowListener, infatti ci si può anche servire di essa per chiudere una finestra :

import java.io.event.*;

public void ChiudiApplicazione extends WindowAdapter {

public void windowClosing(WindowEvent evt) {

System.exit(0);

}

}

e nella classe che usa il frame occorre istanziare un oggetto del tipo ChiudiApplicazione e scrivere addWindowListener(nome_oggetto).

Non tratterò gli eventi di modifica perché riguardano solo le barre di scorrimento.

Non resta ora che mettere in pratica le informazioni fornite, provando ad esempio a generare una finestra con due bottoni attivi che cambiano il contenuto di un'etichetta, oppure rendere funzionale l'interfaccia per la connessione presentata come esempio.

Spero di esservi stato di aiuto o, almeno, di aver gettato le basi per la progettazione di una GUI.

Ritengo comunque utile, ai fini di comprensione delle tecniche OOP, l'utilizzo di Swing.

Per qualsiasi tipo di commento potete contattarmi all'e-mail in cima all'ipertesto.

Buon lavoro.

Maux