Gestione degli eventi di azione su oggetti JButton

Introduzione: Il modello a delegazione
In Java il modello di gestione degli eventi (detto a delegazione) prevede che si compiano le seguenti azioni:

1) Individuazione della sorgente dell’evento
Il programmatore stabilisce quale oggetto darà origine a un evento di interesse. Ad esempio un pulsante in una GUI genera un evento quando l’utente vi clicca sopra. L’oggetto in questione viene chiamato sorgente dell’evento.

2) Definizione del rilevatore dell’evento
Il programmatore definisce una classe, detta rilevatore dell’evento (in inglese listener), contenente la descrizione delle operazioni da eseguire per gestire l’evento che si è verificato. La classe rilevatore deve sempre implementare un’interfaccia speciale, detta interfaccia rilevatore.

3) Registrazione del rilevatore presso la sorgente
Il programmatore deve associare il rilevatore alla sorgente dell’evento. Quando si verifica l’evento, la sorgente invia un oggetto evento a tutti i rilevatori registrati, in modo che essi possano compiere le azioni predisposte. Tutti gli eventi che non hanno un rilevatore, sono ignorati.

Gestione dell’evento clic su un pulsante
L’unico evento disponibile per i pulsanti è la pressione su di essi con il mouse. Vediamo, attraverso un esempio, quali azioni deve intraprendere il programmatore affinché l’applicazione gestisca tale evento. Costruiamo una GUI contenente un solo pannello, inserito in un frame in posizione centrale, e un unico pulsante etichettato con la stringa Giallo. Si vuole gestire il seguente evento: al clic del mouse sul pulsante, il pannello deve cambiare il colore di sfondo in giallo.
import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; public class InteractiveFrame { public static void main(String[] args) { final String TITOLO ="Colora il pannello"; JFrame frame = new JFrame(TITOLO); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel pane = new JPanel(); JButton button = new JButton("Colora"); pane.add(button); frame.add(pane); frame.pack(); Bocchi Cinzia Ultimo aggiornamento: 05/11/2011

1

frame.setVisible(true); } }

Il frame creato

1) Individuazione della sorgente dell’evento
La sorgente dell’evento è il pulsante button.

2) Definizione del rilevatore dell’evento
Il rilevatore dell’evento clic su un pulsante è una classe che deve – implementare l’interfaccia ActionListener; – fornire il codice per ogni metodo dell'interfaccia. A questo punto è opportuno ricordare che le interfacce differiscono dalle classi in quanto non hanno variabili di istanza e non forniscono alcuna implementazione dei metodi che definiscono. In altre parole, un’interfaccia specifica solo quali sono i metodi e non che cosa fanno. Le classi che implementano un’interfaccia hanno l’obbligo di fornire il codice per ogni metodo che essa definisce. Inoltre, tutti i metodi di un’interfaccia sono public. La sintassi da utilizzare per implementare un'interfaccia è: class Rilevatore implements Interfaccia Nel nostro esempio, se chiamiamo il rilevatore ButtonListener, dovremo scrivere: class ButtonListener implements ActionListener Per fornire il codice di tutti i metodi dell'interfaccia, dobbiamo ovviamente conoscere quali sono tali metodi. L'interfaccia ActionListener possiede un solo metodo actionPerformed, che dovrà essere implementato. La firma del metodo actionPerformed è: public void actionPerformed (ActionEvent e)

Tornando all’esempio, possiamo definire (in un file separato) la classe rilevatore come segue:
Bocchi Cinzia Ultimo aggiornamento: 05/11/2011

2

import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class ButtonListener implements ActionListener { public void actionPerformed(ActionEvent e){ //codice che gestisce l'evento } }

3) Registrazione del rilevatore presso la sorgente
Per registrare il rilevatore presso la sorgente si crea un’istanza della classe rilevatore e si invoca il metodo addActionListener, passandogli come parametro l’istanza creata. Nel codice della classe InteractiveFrame dovremo aggiungere, dopo la creazione del pulsante:
ButtonListener listener = new ButtonListener(); button.addActionListener(listener);

Una forma abbreviata della precedente scrittura, adottabile se non necessario fornire un nome all'istanza della classe ButtonListener, è:
button.addActionListener(new ButtonListener());

Le classi rilevatori di eventi devono sempre contenere la direttiva di importazione import java.awt.event.*.

Scrittura del codice per la gestione dell'evento
Il metodo actionPerformed della classe ButtonListener, deve cambiare il colore di sfondo del pannello; il codice potrebbe essere il seguente:
1 2 3 4 5 6 7 public void actionPerformed(ActionEvent e){ Random randomGenerator = new Random(); int red = randomGenerator.nextInt(MAX_VALUE); int green = randomGenerator.nextInt(MAX_VALUE); int blue = randomGenerator.nextInt(MAX_VALUE); pane.setBackground(new Color(red, green, blue)); }

Rigo 2: crea una istanza della classe java.util.Random; la classe Random consente di generare un flusso di numeri random. Righi 3-5: il metodo nextInt restituisce un numero random intero compreso tra 0 (incluso) e il parametro specificato (escluso); la costante MAX_VALUE, definita nella classe ButtonListener, vale 256 poiché 255 è il massimo valore che ogni componente di un colore RGB può assumere. Il codice riportato, però, genera un errore in fase di compilazione: il compilatore non è in grado di trovare la variabile pane. Infatti, pane è una variabile di istanza della classe InteractiveFrame e il suo riferimento non è noto alla classe ButtonListener.

Bocchi Cinzia Ultimo aggiornamento: 05/11/2011

3

Una prima soluzione consiste nel comunicare tale riferimento alla classe ButtonListener, mediante il passaggio di un parametro. Vedremo in seguito un'altra soluzione che fa uso di classi interne.

Procedimento 1. Definire nella classe rilevatore, una variabile di istanza privata dello stesso
"tipo" della variabile di cui si deve passare il riferimento.

2. Aggiungere al costruttore della classe rilevatore un parametro che sia dello
stesso "tipo" della variabile appena dichiarata. 3. Inserire nel corpo del costruttore l'assegnazione: <var di istanza> = <parametro>; 4. Nella classe ove è definita la sorgente dell’evento, modificare la chiamata al costruttorer della classe rilevatore, specificando il parametro attuale necessario
public class ButtonListener implements ActionListener { public static final int MAX_VALUE = 256; private JPanel pane;

1

public ButtonListener(JPanel pane){ 2 this.pane = pane; 3 } public void actionPerformed(ActionEvent e){ Random randomGenerator = new Random(); int red = randomGenerator.nextInt(MAX_VALUE); int green = randomGenerator.nextInt(MAX_VALUE); int blue = randomGenerator.nextInt(MAX_VALUE); pane.setBackground(new Color(red, green, blue)); } } public class InteractiveFrame { public static void main(String[] args) { ................ button.addActionListener(new ButtonListener(pane)); ................ }

4

}

A questo punto, la classe ButtonListener conosce il riferimento al pannello e il codice contenuto nel corpo del metodo actionPerformed, non genera più errori.

Bocchi Cinzia Ultimo aggiornamento: 05/11/2011

4

Codice completo dell’esempio
InteractiveFrame.java
import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; public class InteractiveFrame { public static void main(String[] args) { final String TITOLO ="Colora il pannello"; JFrame frame = new JFrame(TITOLO); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel pane = new JPanel(); JButton button = new JButton("Colora"); //*****Registrazione del rilevatore di evento***** button.addActionListener(new ButtonListener(pane)); //************************************************ pane.add(button); frame.add(pane); frame.pack(); frame.setVisible(true);

} }

ButtonListener.java
import import import import java.awt.Color; java.awt.event.ActionEvent; java.awt.event.ActionListener; java.util.Random;

import javax.swing.JPanel; public class ButtonListener implements ActionListener { public static final int MAX_VALUE = 256; private JPanel pane; public ButtonListener(JPanel pane){ this.pane = pane; } public void actionPerformed(ActionEvent e){ Random randomGenerator = new Random(); int red = randomGenerator.nextInt(MAX_VALUE); int green = randomGenerator.nextInt(MAX_VALUE); int blue = randomGenerator.nextInt(MAX_VALUE); pane.setBackground(new Color(red, green, blue)); } }

Quest'opera è stata rilasciata con licenza Creative Commons Attribution-ShareAlike 3.0 Unported. Per leggere una copia della licenza visita il sito web http://creativecommons.org/licenses/by-sa/3.0/ o spedisci una lettera a Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. Bocchi Cinzia Ultimo aggiornamento: 05/11/2011

5