5. Interfacce grafiche
In questa sede intendiamo illustrare come realizzare interfacce grafiche con JAVA. Vediamo innanzitutto quali sono le classi di base che ci consentono di costruire un'interfaccia grafica. In una prima fase non utilizzeremo alcun strumento di generazione automatica. Successivamente utilizzeremo JBuilder, uno strumento di sviluppo di Borland/Inprise che facilita lo sviluppo di applicazioni Java e in particolare la creazione di interfacce grafiche.
5.1. Nozioni di base sulle interfacce grafiche
5.1.1. Una finestra semplice
Consideriamo il codice seguente:
// classi importate
import javax.swing.*;
import java.awt.*;
// la classe modulo
public class form1 extends JFrame {
// il costruttore
public form1() {
// titolo della finestra
this.setTitle("Mon premier formulaire");
// dimensioni della finestra
this.setSize(new Dimension(300,100));
}//costruttore
// funzione di test
public static void main(String[] args) {
// viene visualizzato il modulo
new form1().setVisible(true);
}
}//classe
L'esecuzione del codice precedente visualizza la seguente finestra:

Un'interfaccia grafica deriva in genere dalla classe base JFrame:
public class form1 extends JFrame {
La classe base JFrame definisce una finestra di base con pulsanti di chiusura, ingrandimento/riduzione, dimensioni regolabili, ecc... e gestisce gli eventi su questi oggetti grafici. Qui specializziamo la classe base assegnandole un titolo e specificandone la larghezza (300 pixel) e l’altezza (100 pixel). Ciò avviene nel suo costruttore:
// il costruttore
public form1() {
// titolo della finestra
this.setTitle("Mon premier formulaire");
// dimensioni della finestra
this.setSize(new Dimension(300,100));
}//costruttore
Il titolo della finestra viene impostato dal metodo setTitle e le sue dimensioni dal metodo setSize. Questo metodo accetta come parametro un oggetto Dimension(largeur,hauteur), dove largeur e hauteur sono rispettivamente la larghezza e l’altezza della finestra espresse in pixel.
Il metodo main avvia l'applicazione grafica nel modo seguente:
new form1().setVisible(true);
Viene quindi creato un modulo di tipo form1 (new form1()) e visualizzato (setVisible(true)), dopodiché l’applicazione si mette in ascolto degli eventi che si verificano sul modulo (clic, spostamenti del mouse, ...) ed esegue quelli gestiti dal modulo stesso. In questo caso, il nostro modulo non gestisce altri eventi oltre a quelli gestiti dalla classe base JFrame (clic sui pulsanti di chiusura, ingrandimento/riduzione, modifica delle dimensioni della finestra, spostamento della finestra, ...).
Quando si testa questo programma avviandolo da una finestra DOS con il comando:
per eseguire il file form1.class, si nota che quando si chiude la finestra visualizzata, non si “riacquista il controllo” nella finestra DOS, come se il programma non fosse terminato. È effettivamente così. L’esecuzione del programma avviene nel modo seguente:
- inizialmente viene avviato un primo thread di esecuzione per eseguire il metodo main
- quando questo crea il modulo e lo visualizza, viene creato un secondo thread per gestire specificamente gli eventi relativi al modulo
- dopo tale creazione e, nel nostro esempio, il thread del metodo main termina e rimane quindi solo il thread di esecuzione dell’interfaccia grafica.
- Quando si chiude la finestra, questa scompare ma non interrompe il thread in cui era in esecuzione
- Per il momento siamo costretti a interrompere questo thread premendo Ctrl-C nella finestra DOS da cui è stata avviata l’esecuzione del programma.
Verifichiamo l’esistenza di due thread distinti, uno in cui viene eseguito il metodo main e l’altro in cui viene eseguita la finestra grafica:
// classi importate
import javax.swing.*;
import java.awt.*;
import java.io.*;
// la classe del modulo
public class form1 extends JFrame {
// il costruttore
public form1() {
// titolo della finestra
this.setTitle("Mon premier formulaire");
// dimensioni della finestra
this.setSize(new Dimension(300,100));
}//costruttore
// funzione di test
public static void main(String[] args) {
// monitoraggio
System.out.println("Début du thread main");
// viene visualizzato il modulo
new form1().setVisible(true);
// monitoraggio
System.out.println("Fin du thread main");
}//main
}//classe
L'esecuzione produce i seguenti risultati:

Si può notare che il thread main è terminato mentre la finestra è ancora visualizzata. La chiusura della finestra non termina il thread in cui era in esecuzione. Per arrestare questo thread, si preme nuovamente Ctrl-C nella finestra DOS.
Per concludere questo esempio, si notino i pacchetti importati:
- javax.swing per la classe JFrame
- java.awt per la classe Dimension
5.1.2. Gestire un evento
Nell’esempio precedente, dovremmo gestire noi stessi la chiusura della finestra in modo che, quando si verifica, l’applicazione venga arrestata, cosa che per ora non avviene. A tal fine, dobbiamo creare un oggetto che “ascolti” gli eventi che si verificano sulla finestra e rilevi l’evento “chiusura della finestra”. Questo oggetto viene chiamato “listener” o gestore di eventi. Esistono diversi tipi di gestori per i vari eventi che possono verificarsi sui componenti di un’interfaccia grafica. Per il componente JFrame, il listener si chiama WindowListener ed è un’interfaccia che definisce i seguenti metodi (cfr. documentazione Java)
Riepilogo dei metodi | ||
void | windowActivated(WindowEvent e) La finestra diventa la finestra attiva | |
void | windowClosed(WindowEvent e) La finestra è stata chiusa | |
void | windowClosing(WindowEvent e) L'utente o il programma ha richiesto la chiusura della finestra | |
void | windowDeactivated(WindowEvent e) La finestra non è più quella attiva | |
void | windowDeiconified(WindowEvent e) La finestra passa dallo stato ridotto allo stato normale | |
void | windowIconified(WindowEvent e) La finestra passa dallo stato normale allo stato ridotto | |
void | windowOpened(WindowEvent e) La finestra diventa visibile per la prima volta | |
Ci sono quindi sette eventi che possono essere gestiti. Tutti i gestori ricevono come parametro un oggetto di tipo WindowEvent che per ora ignoriamo. L'evento che ci interessa in questo caso è la chiusura della finestra, evento che dovrà essere gestito dal metodo windowClosing. Per gestire questo evento, è possibile creare un oggetto Windowlistener utilizzando una classe anonima nel modo seguente:
// creazione di un gestore di eventi
WindowListener win=new WindowListener(){
public void windowActivated(WindowEvent e){}
public void windowClosed(WindowEvent e){}
public void windowClosing(WindowEvent e){System.exit(0);}
public void windowDeactivated(WindowEvent e){}
public void windowDeiconified(WindowEvent e){}
public void windowIconified(WindowEvent e){}
public void windowOpened(WindowEvent e){}
};//definizione win
Il nostro gestore di eventi che implementa l'interfaccia WindowListener deve definire i sette metodi di tale interfaccia. Poiché vogliamo gestire solo la chiusura della finestra, definiamo il codice solo per il metodo windowClosing. Quando si verificheranno gli altri eventi, ne saremo avvisati ma non faremo nulla. Cosa faremo quando ci verrà segnalato che la finestra sta per chiudersi (windowClosing)? Chiuderemo l’applicazione:
public void windowClosing(WindowEvent e){System.exit(0);}
Abbiamo qui un oggetto in grado di gestire gli eventi di una finestra in generale. Come lo associamo a una finestra specifica? La classe JFrame dispone di un metodo addWindowListener(WindowListener win) che consente di associare un gestore di eventi «finestra» a una determinata finestra. Quindi, qui, nel costruttore della finestra scriveremo:
// creazione di un gestore di eventi
WindowListener win=new WindowListener(){
public void windowActivated(WindowEvent e){}
public void windowClosed(WindowEvent e){}
public void windowClosing(WindowEvent e){System.exit(0);}
public void windowDeactivated(WindowEvent e){}
public void windowDeiconified(WindowEvent e){}
public void windowIconified(WindowEvent e){}
public void windowOpened(WindowEvent e){}
};//definizione win
// questo gestore di eventi gestirà gli eventi della finestra corrente
this.addWindowListener(win);
Il programma completo è il seguente:
// classi importate
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.awt.event.*;
// la classe modulo
public class form2 extends JFrame {
// il costruttore
public form2() {
// titolo della finestra
this.setTitle("Mon premier formulaire");
// dimensioni della finestra
this.setSize(new Dimension(300,100));
// creazione di un gestore di eventi
WindowListener win=new WindowListener(){
public void windowActivated(WindowEvent e){}
public void windowClosed(WindowEvent e){}
public void windowClosing(WindowEvent e){System.exit(0);}
public void windowDeactivated(WindowEvent e){}
public void windowDeiconified(WindowEvent e){}
public void windowIconified(WindowEvent e){}
public void windowOpened(WindowEvent e){}
};//definizione win
// questo gestore di eventi gestirà gli eventi della finestra corrente
this.addWindowListener(win);
}//costruttore
// funzione di test
public static void main(String[] args) {
// si visualizza il modulo
new form2().setVisible(true);
}//main
}//classe
Il pacchetto java.awt.event contiene l'interfaccia WindowListener. Quando si esegue questo programma e si chiude la finestra che è apparsa, nella finestra DOS in cui è stato avviato il programma si nota la fine dell'esecuzione del programma, cosa che prima non accadeva.
Nel nostro programma, la creazione dell’oggetto incaricato di gestire gli eventi della finestra risulta un po’ macchinosa, in quanto si è costretti a definire metodi anche per eventi che non si desidera gestire. In questo caso, invece di utilizzare l’interfaccia WindowListener, è possibile utilizzare la classe WindowAdapter. Quest’ultima implementa l’interfaccia WindowListener, con sette metodi vuoti. Derivando dalla classe WindowAdapter e ridefinendo solo i metodi che ci interessano, otteniamo lo stesso risultato che avremmo con l’interfaccia WindowListener, ma senza dover definire i metodi che non ci interessano. La sequenza
- definizione del gestore di eventi
- associazione del gestore alla finestra
può essere eseguita nel modo seguente nel nostro esempio:
// creazione di un gestore di eventi
WindowAdapter win=new WindowAdapter(){
public void windowClosing(WindowEvent e){System.exit(0);}
};//definizione win
// questo gestore di eventi gestirà gli eventi della finestra corrente
this.addWindowListener(win);
Qui utilizziamo una classe anonima che deriva dalla classe WindowAdapter e ridefinisce il suo metodo windowClosing. Il programma diventa quindi:
// classi importate
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.awt.event.*;
// la classe modulo
public class form2 extends JFrame {
// il costruttore
public form2() {
// titolo della finestra
this.setTitle("Mon premier formulaire");
// dimensioni della finestra
this.setSize(new Dimension(300,100));
// creazione di un gestore di eventi
WindowAdapter win=new WindowAdapter(){
public void windowClosing(WindowEvent e){System.exit(0);}
};//definizione win
// questo gestore di eventi gestirà gli eventi della finestra corrente
this.addWindowListener(win); }//costruttore
// funzione di test
public static void main(String[] args) {
// si visualizza il modulo
new form2().setVisible(true);
}//main
}//classe
Fornisce gli stessi risultati del programma precedente, ma è più semplice da scrivere.
5.1.3. Un modulo con un pulsante
Aggiungiamo ora un pulsante alla nostra finestra:
// classi importate
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.awt.event.*;
// la classe del modulo
public class form3 extends JFrame {
// un pulsante
JButton btnTest=null;
Container conteneur=null;
// il costruttore
public form3() {
// titolo della finestra
this.setTitle("Formulaire avec bouton");
// dimensioni della finestra
this.setSize(new Dimension(300,100));
// creazione di un gestore di eventi
WindowAdapter win=new WindowAdapter(){
public void windowClosing(WindowEvent e){System.exit(0);}
};//definizione win
// questo gestore di eventi gestirà gli eventi della finestra corrente
this.addWindowListener(win);
// si recupera il contenitore della finestra
conteneur=this.getContentPane();
// si sceglie un gestore di formattazione dei componenti in questo contenitore
conteneur.setLayout(new FlowLayout());
// si crea un pulsante
btnTest=new JButton();
// si imposta la sua etichetta
btnTest.setText("Test");
// si aggiunge il pulsante al contenitore
conteneur.add(btnTest);
}//costruttore
// funzione di test
public static void main(String[] args) {
// si visualizza il modulo
new form3().setVisible(true);
}//main
}//classe
Una finestra JFrame dispone di un contenitore in cui è possibile inserire componenti grafici (pulsanti, caselle di controllo, elenchi a discesa, ecc.). Questo contenitore è accessibile tramite il metodo getContentPane della classe JFrame:
Container conteneur=null;
..........
// si recupera il contenitore della finestra
conteneur=this.getContentPane();
Ogni componente viene inserito nel contenitore tramite il metodo add della classe Container. Pertanto, per inserire il componente C nell'oggetto conteneur precedente, si scriverà:
Dove viene posizionato questo componente nel contenitore? Esistono diversi gestori di disposizione dei componenti denominati XXXLayout, con XXX uguale, ad esempio, a Border, Flow, ... Ogni gestore di layout presenta le proprie caratteristiche specifiche. Ad esempio, il gestore FlowLayout dispone i componenti in riga partendo dalla parte superiore del modulo. Una volta completata una riga, i componenti vengono posizionati nella riga successiva. Per associare un gestore di layout a una finestra JFrame, si utilizza il metodo setLayout della classe JFrame nella forma:
Pertanto, nel nostro esempio, per associare un gestore di tipo FlowLayout alla finestra, abbiamo scritto:
// si sceglie un gestore di formattazione dei componenti in questo contenitore
conteneur.setLayout(new FlowLayout());
È possibile non utilizzare un gestore di layout e scrivere:
In questo caso, sarà necessario specificare le coordinate precise del componente all’interno del contenitore nella forma (x, y, larghezza, altezza), dove (x, y) sono le coordinate dell’angolo superiore sinistro del componente nel contenitore. È questo il metodo che useremo più spesso d’ora in poi.
Ora sappiamo come vengono posizionati i componenti nel contenitore (add) e dove (setLayout). Resta da conoscere i
componenti che è possibile inserire in un contenitore. In questo caso inseriamo un pulsante implementato dalla classe javax.swing.JButton:
JButton btnTest=null;
..........
// si crea un pulsante
btnTest=new JButton();
// si imposta la sua etichetta
btnTest.setText("Test");
// si aggiunge il pulsante al contenitore
conteneur.add(btnTest);
Quando si esegue il programma, viene visualizzata la seguente finestra:

Se si ridimensiona il modulo sopra riportato, viene automaticamente richiamato il gestore di layout del contenitore per riposizionare i componenti:

Questo è il principale vantaggio dei gestori di layout: mantenere una disposizione coerente dei componenti al variare delle dimensioni del contenitore. Utilizziamo il gestore di layout null per vedere la differenza. Il pulsante viene ora posizionato nel contenitore tramite le seguenti istruzioni:
// si seleziona un gestore di formattazione dei componenti in questo contenitore
conteneur.setLayout(null);
// si crea un pulsante
btnTest=new JButton();
// si imposta il testo del pulsante
btnTest.setText("Test");
// si impostano la posizione e le dimensioni
btnTest.setBounds(10,20,100,20);
// si aggiunge il pulsante al contenitore
conteneur.add(btnTest);
Qui si posiziona esplicitamente il pulsante nel punto (10,20) del modulo e se ne impostano le dimensioni a 100 pixel di larghezza e 20 pixel di altezza. La nuova finestra diventa la seguente:

Se si ridimensiona la finestra, il pulsante rimane nella stessa posizione.

Se si fa clic sul pulsante Test, non accade nulla. Infatti, non abbiamo ancora associato alcun gestore di eventi al pulsante. Per conoscere il tipo di gestori di eventi disponibili per un determinato componente, è possibile cercare nella definizione della sua classe i metodi addXXXListener che consentono di associare un gestore di eventi al componente. La classe javax.swing.JButton deriva dalla classe javax.swing.AbstractButton, nella quale sono presenti i seguenti metodi:
Riepilogo dei metodi | ||
void | addActionListener(ActionListener l) | |
void | addChangeListener(ChangeListener l) | |
void | addItemListener(ItemListener l) | |
In questo caso, è necessario consultare la documentazione per sapere quale gestore di eventi gestisce il clic sul pulsante. Si tratta dell'interfaccia ActionListener. Questa definisce un solo metodo:
Riepilogo dei metodi | ||
void | actionPerformed(ActionEvent e) | |
Il metodo riceve un parametro ActionEvent che per il momento ignoreremo. Per gestire il clic sul pulsante btntest del nostro programma, gli associamo innanzitutto un gestore di eventi:
btnTest.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt){
btnTest_clic(evt);
}
}//classe anonima
);//gestore di eventi
In questo caso, il metodo actionPerformed rimanda al metodo btnTest_clic, che definiamo come segue:
public void btnTest_clic(ActionEvent evt){
// monitoraggio console
System.out.println("clic sur bouton");
}//btnTest_click
Ogni volta che l'utente fa clic sul pulsante Test, viene visualizzato un messaggio sulla console. È quanto mostra la seguente esecuzione:

Il programma completo è il seguente:
// classi importate
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.awt.event.*;
// classe modulo
public class form4 extends JFrame {
// un pulsante
JButton btnTest=null;
Container conteneur=null;
// il costruttore
public form4() {
// titolo della finestra
this.setTitle("Formulaire avec bouton");
// dimensioni della finestra
this.setSize(new Dimension(300,100));
// creazione di un gestore di eventi
WindowAdapter win=new WindowAdapter(){
public void windowClosing(WindowEvent e){System.exit(0);}
};//definizione win
// questo gestore di eventi gestirà gli eventi della finestra corrente
this.addWindowListener(win);
// si recupera il contenitore della finestra
conteneur=this.getContentPane();
// si sceglie un gestore di formattazione dei componenti in questo contenitore
conteneur.setLayout(null);
// si crea un pulsante
btnTest=new JButton();
// si imposta la sua etichetta
btnTest.setText("Test");
// si definiscono la posizione e le dimensioni
btnTest.setBounds(10,20,100,20);
// gli si associa un gestore di eventi
btnTest.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt){
btnTest_clic(evt);
}
}//classe anonima
);//gestore di eventi
// si aggiunge il pulsante al contenitore
conteneur.add(btnTest);
}//costruttore
public void btnTest_clic(ActionEvent evt){
// monitoraggio console
System.out.println("clic sur bouton");
}//btnTest_click
// funzione di test
public static void main(String[] args) {
// viene visualizzato il modulo
new form4().setVisible(true);
}//main
}//classe
5.1.4. I gestori di eventi
I principali componenti Swing che presenteremo sono le finestre (JFrame), i pulsanti (JButton), le caselle di controllo (JCheckBox), i pulsanti di opzione (JButtonRadio), i menu a tendina (JComboBox), gli elenchi (JList), i cursori (JScrollBar), le etichette (JLabel), le caselle di immissione a riga singola (JTextField) o a più righe (JTextArea), i menu (JMenuBar), gli elementi di menu (JMenuItem).
Le tabelle seguenti riportano un elenco di alcuni gestori di eventi e degli eventi a cui sono associati.
Gestore | Componente/i | Metodo di registrazione | Evento |
ActionListener | JButton, JCheckbox, JButtonRadio, JMenuItem | public void addActionListener(ActionListener) | clic sul pulsante, sulla casella di controllo, sul pulsante di opzione, sull'elemento di menu |
JTextField | |||
ItemListener | JComboBox, JList | public void addItemListener(ItemListener) | L'elemento selezionato è cambiato |
InputMethodListener | JTextField, JTextArea | public void addMethodInputListener(InputMethodListener) | il testo nel campo di immissione è cambiato oppure la posizione del cursore di immissione è cambiata |
CaretListener | JTextField, JTextArea | public void addcaretListener(CaretListener) | Il cursore di immissione ha cambiato posizione |
AdjustmentListener | JScrollBar | public void addAdjustmentListener(AdjustmentListener) | il valore del variatore è cambiato |
MouseMotionListener | public void addMouseMotionListener(MouseMotionListener) | il mouse si è spostato | |
WindowListener | JFrame | public void addWindowlistener(WindowListener) | evento finestra |
MouseListener | public void addMouselistener(MouseListener) | eventi del mouse (clic, ingresso/uscita dall'area di un componente, pulsante premuto, rilascio) | |
FocusListener | public void addFocuslistener(FocusListener) | evento focus (acquisito, perso) | |
KeyListener | public void addKeylistener(KeyListener) | evento tastiera (tasto digitato, premuto, rilasciato) |
Componente | Metodo di registrazione dei gestori di eventi |
JButton | public void addActionListener(ActionListener) |
JCheckbox | public void addItemListener(ItemListener) |
JCheckboxMenuItem | public void addItemListener(ItemListener) |
JComboBox | public void addItemListener(ItemListener) public void addActionListener(ActionListener) |
Container | public void addContainerListener(ContainerListener) |
JComponent | public void addComponentListener(ComponentListener) public void addFocusListener(FocusListener) public void addKeyListener(KeyListener) public void addMouseListener(MouseListener) public void addMouseMotionListener(MouseMotionListener) |
JFrame | public void addWindowlistener(WindowListener) |
JList | public void addItemListener(ItemListener) |
JMenuItem | public void addActionListener(ActionListener) |
JPanel | come contenitore |
JScrollPane | come contenitore |
JScrollBar | public void addAdjustmentListener(AdjustmentListener) |
JTextComponent | public void addInputMethodListener(InputMethodListener) public void addCaretListener(CaretListener) |
JTextArea | come JTextComponent |
JTextField | come JTextComponent public void addActionListener(ActionListener) |
Tutti i componenti, ad eccezione di quelli di tipo TextXXX, essendo derivati dalla classe JComponent, possiedono anche i metodi associati a tale classe.
5.1.5. I metodi dei gestori di eventi
La tabella seguente elenca i metodi che devono essere implementati dai diversi gestori di eventi.
Interfaccia | Metodi |
ActionListener | public void actionPerformed(ActionEvent) |
AdjustmentListener | public void adjustmentValueChanged(AdjustmentEvent) |
ComponentListener | public void componentHidden(ComponentEvent) public void componentMoved(ComponentEvent) public void componentResized(ComponentEvent) public void componentShown(ComponentEvent) |
ContainerListener | public void componentAdded(ContainerEvent) public void componentRemoved(ContainerEvent) |
FocusListener | public void focusGained(FocusEvent) public void focusLost(FocusEvent) |
ItemListener | public void itemStateChanged(ItemEvent) |
KeyListener | public void keyPressed(KeyEvent) public void keyReleased(KeyEvent) public void keyTyped(KeyEvent) |
MouseListener | public void mouseClicked(MouseEvent) public void mouseEntered(MouseEvent) public void mouseExited(MouseEvent) public void mousePressed(MouseEvent) public void mouseReleased(MouseEvent) |
MouseMotionListener | public void mouseDragged(MouseEvent) public void mouseMoved(MouseEvent) |
TextListener | public void textValueChanged(TextEvent) |
InputmethodListener | public void InputMethodTextChanged(InputMethodEvent) public void caretPositionChanged(InputMethodEvent) |
CaretLisetner | public void caretUpdate(CaretEvent) |
WindowListener | public void windowActivated(WindowEvent) public void windowClosed(WindowEvent) public void windowClosing(WindowEvent) public void windowDeactivated(WindowEvent) public void windowDeiconified(WindowEvent) public void windowIconified(WindowEvent) public void windowOpened(WindowEvent) |
5.1.6. Le classi adattatrici
Come abbiamo visto per l'interfaccia WindowListener, esistono classi denominate XXXAdapter che implementano le interfacce XXXListener con metodi vuoti. Un gestore di eventi derivato da una classe XXXAdapter può quindi implementare solo una parte dei metodi dell’interfaccia XXXListener, ovvero quelli di cui l’applicazione ha bisogno.
Supponiamo di voler gestire i clic del mouse su un componente Frame f1. Si potrebbe associargli un gestore di eventi tramite:
e scrivere:
public class gestionnaireSouris implements MouseListener{
// si scrivono i 5 metodi dell'interfaccia MouseListener
// mouseClicked, ..., mouseReleased)
}// fine classe
Poiché si desidera gestire solo i clic del mouse, è tuttavia preferibile scrivere:
public class gestionnaireSouris extends MouseAdapter{
// si scrive un unico metodo, quello che gestisce i clic del mouse
public void mouseClicked(MouseEvent evt){
…
}
}// fine classe
La tabella seguente riporta le classi di adattatori dei diversi gestori di eventi:
Gestore di eventi | Adattatore |
ComponentListener | ComponentAdapter |
ContainerListener | ContainerAdapter |
FocusListener | FocusAdapter |
KeyListener | KeyAdapter |
MouseListener | MouseAdapter |
MouseMotionListener | MouseMotionAdapter |
WindowListener | WindowAdapter |
5.1.7. Conclusione
Abbiamo appena illustrato i concetti di base della creazione di interfacce grafiche in Java:
- creazione di una finestra
- creazione di componenti
- associazione dei componenti alla finestra tramite un gestore di layout
- associazione dei gestori di eventi ai componenti
Ora, invece di costruire interfacce grafiche “a mano” come abbiamo appena fatto, useremo JBuilder, uno strumento di sviluppo Java di Borland/Inprise nella sua versione 4, e supérieure.Nous utilizzeremo i componenti della libreria java.swing attualmente raccomandata da Sun, creatore di Java.
5.2. Creazione di un'interfaccia grafica con JBuilder
5.2.1. Il nostro primo progetto con JBuilder
Per familiarizzare con JBuilder, creiamo un'applicazione molto semplice: una finestra vuota.
- Avviate JBuilder e selezionate l’opzione File/Nuovo progetto. Verrà quindi visualizzata la prima pagina di una procedura guidata:

- Compilate i seguenti campi:
Nome del progetto | Inizio Questo comporterà la creazione di un file di progetto début.jpr nella cartella indicata nel campo "Nome della cartella del progetto" |
Percorso radice | Indicare la cartella in cui verrà creata la cartella del progetto che si intende creare. |
Nome della cartella del progetto | indicare il nome della cartella in cui verranno inseriti tutti i file del progetto. Questa cartella verrà creata nella directory indicata nel campo "Percorso radice" |
I file sorgente (.java, .html, ...), i file di destinazione (.class, ...) e i file di backup potrebbero essere collocati in cartelle diverse. Lasciando vuoti i relativi campi, verranno collocati nella stessa cartella del progetto.
Inserite [suivant]
- Una schermata conferma le scelte effettuate nella fase precedente

Selezionare [suivant]
- Una nuova schermata richiede di specificare le caratteristiche del progetto:

Selezionare [terminer]
- Verificare che l'opzione Voir/projet sia selezionata. Nella finestra a sinistra dovrebbe essere visibile la struttura del progetto.

- Ora creiamo un'interfaccia grafica in questo progetto. Selezionate l'opzione Fichier/Nouveau/Application:

Nel campo classe, inserite il nome della classe che verrà creata. In questo caso abbiamo utilizzato lo stesso nome del progetto.
Eseguire [suivant]
- Viene visualizzata la schermata seguente:

Classe | interfaceDébut È il nome della classe corrispondente alla finestra che verrà creata |
Titolo | È il testo che apparirà nella barra del titolo della finestra |
Si noti che sopra abbiamo specificato che la finestra venga centrata sullo schermo all'avvio dell'applicazione.
Digitare [Terminer]
- È proprio ora che JBuilder si rivela utile.
- Genera i file sorgente .java delle due classi di cui abbiamo specificato i nomi: la classe dell’applicazione e quella dell’interfaccia grafica. Questi due file compaiono nella struttura del progetto nella finestra a sinistra

- Per accedere al codice generato per le due classi, basta fare doppio clic sul file .java corrispondente. Torneremo in seguito sul codice generato.
- Verificate che l’opzione Voir/Structure sia selezionata. Consente di visualizzare la struttura della classe attualmente selezionata (doppio clic sul file .java). Ecco, ad esempio, la struttura della classe début:

Qui si possono vedere:
-
le librerie importate (imports)
-
che è presente un costruttore début()
-
che esiste un metodo statico main()
-
che esiste un attributo packFrame
Qual è l’utilità di avere accesso alla struttura di una classe?
-
si ha una visione d'insieme della stessa. Ciò è utile se la classe è complessa.
-
è possibile accedere al codice di un metodo cliccandoci sopra nella finestra della struttura della classe. Anche in questo caso è utile se la classe contiene centinaia di righe. Non è necessario scorrere tutte le righe per trovare il codice che si sta cercando.
Il codice generato da JBuilder è già utilizzabile. Selezionate Esegui/Esegui progetto oppure F9 e otterrete la finestra richiesta:

Inoltre, si chiude correttamente quando si fa clic sul pulsante di chiusura della finestra. Abbiamo appena creato la nostra prima interfaccia grafica. Possiamo salvare il nostro progetto tramite l’opzione File/Chiudi progetti:

Premendo Tous, tutti i progetti presenti nella finestra sopra riportata verranno selezionati. OK li chiuderà. Se siamo curiosi di accedere, tramite Esplora risorse di Windows, alla cartella del nostro progetto (quella indicata all’assistente all’inizio della configurazione del progetto), vi troveremo i seguenti file:

Nel nostro esempio, avevamo richiesto che tutti i file (sorgente .java, destinazione .class, backup .jpr~) fossero nella stessa cartella del progetto .jpr.
5.2.2. I file generati da JBuilder per un'interfaccia grafica
Proviamo ora a dare un'occhiata ai file sorgente .java generati da JBuilder. È importante saper interpretare il codice generato, poiché nella maggior parte dei casi ci troveremo a dover aggiungere del codice a quello già generato. Iniziamo recuperando il nostro progetto: File/Apri progetto e selezioniamo il progetto début.jpr. Ritroviamo il progetto creato in precedenza.
5.2.2.1. La classe principale
Esaminiamo la classe début.java facendo doppio clic sul suo nome nella finestra che mostra l’elenco dei file del progetto. Abbiamo il seguente codice:
import javax.swing.UIManager;
import java.awt.*;
public class début {
boolean packFrame = false;
/**Creazione dell'applicazione*/
public début() {
interfaceDébut frame = new interfaceDébut();
//Convalidare i frame con dimensioni predefinite
//Comprimere i riquadri con informazioni sulle dimensioni preferite - ad es. in base alla loro disposizione
if (packFrame) {
frame.pack();
}
else {
frame.validate();
}
//Centrare la finestra
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = frame.getSize();
if (frameSize.height > screenSize.height) {
frameSize.height = screenSize.height;
}
if (frameSize.width > screenSize.width) {
frameSize.width = screenSize.width;
}
frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);
frame.setVisible(true);
}
/**Metodo principale*/
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(Exception e) {
e.printStackTrace();
}
new début();
}
}
Commentiamo il codice generato:
- la funzione main imposta l'aspetto della finestra (setLookAndFeel) e crea un'istanza della classe début.
- Viene quindi eseguito il costruttore début(). Esso crea un'istanza frame della classe della finestra (new interfaceDébut()). Quest'ultima viene costruita ma non visualizzata.
- La finestra viene quindi ridimensionata in base alle informazioni disponibili per ciascuno dei suoi componenti (frame.validate). A questo punto inizia la sua esistenza autonoma, visualizzandosi e rispondendo alle richieste dell’utente.
- La finestra viene centrata sullo schermo, poiché ciò era stato richiesto durante la configurazione della finestra con l’assistente.
Vediamo cosa si otterrebbe se riducessimo il codice début.java al minimo indispensabile, come abbiamo fatto all’inizio del capitolo. Creiamo una nuova classe. Selezionate l’opzione File/Nuova classe:

Assegnate alla nuova classe il nome début2 e modificate [Terminer]. Nel progetto compare un nuovo file:

Il file début2.java viene ridotto alla sua forma più semplice:
Completiamo la classe come segue:
public class début2 {
// funzione principale
public static void main(String args[]){
// crea la finestra
new interfaceDébut().show(); // oppure new interfaceDébut.setVisible(true);
}//main
}//classe inizio2
La funzione main crea un'istanza della finestra interfaceDébut e la visualizza (show). Prima di eseguire il nostro progetto, è necessario segnalare che la classe contenente la funzione main da eseguire è ora la classe début2. Fare clic con il tasto destro del mouse sul progetto début.jpr e selezionare l’opzione propriétés, quindi la scheda Exécution:
21

Qui è indicato che la classe principale è début (1). Premere il pulsante (2) per selezionare un’altra classe principale:

Scegliere début2 e impostare [OK].

Selezionare [OK] per confermare la scelta, quindi avviare l'esecuzione del progetto tramite Esegui/Esegui progetto o F9. Si ottiene la stessa finestra della classe début, tranne per il fatto che non è centrata poiché in questo caso non è stato richiesto. D'ora in poi non presenteremo più la classe principale generata da JBuilder poiché fa sempre la stessa cosa: creare una finestra. D'ora in poi ci concentreremo sulla classe di quest'ultima.
5.2.2.2. La classe della finestra
Diamo ora un’occhiata al codice generato per la classe interfaceDébut:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class interfaceDébut extends JFrame {
JPanel contentPane;
BorderLayout borderLayout1 = new BorderLayout();
/**Creare il frame*/
public interfaceDébut() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inizializzare il componente*/
private void jbInit() throws Exception {
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(borderLayout1);
this.setSize(new Dimension(400, 300));
this.setTitle("Ma première interface graphique avec Jbuilder");
}
/**Sostituito, così possiamo uscire quando la finestra viene chiusa*/
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
}
}
5.2.2.2.1. Le librerie importate
Si tratta delle librerie java.awt, java.awt.event e javax.swing. Le prime due erano le uniche disponibili per la creazione di interfacce grafiche con le prime versioni di Java. La libreria javax.swing è più recente. In questo caso, è necessaria per la finestra di tipo JFrame qui utilizzata.
5.2.2.2.2. Gli attributi
JPanel è un tipo di contenitore in cui è possibile inserire componenti. BorderLayout è uno dei tipi di gestori di layout disponibili per posizionare i componenti all’interno del contenitore. In tutti i nostri esempi non utilizzeremo alcun gestore di formattazione e posizioneremo noi stessi i componenti in un punto specifico del contenitore. A tal fine, utilizzeremo il gestore di formattazione null.
5.2.2.2.3. Il generatore della finestra
/**Creare il frame*/
public interfaceDébut() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inizializzare il componente*/
private void jbInit() throws Exception {
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(borderLayout1);
this.setSize(new Dimension(400, 300));
this.setTitle("Ma première interface graphique avec Jbuilder");
}
- Il costruttore inizia affermando che gestirà gli eventi sulla finestra (enableEvents), quindi avvia il metodo jbInit.
- Viene ottenuto (getContentPane) il contenitore (JPanel) della finestra (JFrame)
- Viene impostato il gestore di formattazione (setLayout)
- La dimensione della finestra è stata impostata (setSize)
- Il titolo della finestra è stato impostato (setTitle)
5.2.2.2.4. Il gestore degli eventi
/**Sostituito, in modo da poter uscire quando la finestra viene chiusa*/
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
Il costruttore aveva specificato che la classe avrebbe gestito gli eventi della finestra. È il metodo processWindowEvent a svolgere questo compito. Inizia trasmettendo alla sua classe padre (JFrame) l’evento WindowEvent ricevuto; se quest’ultimo è l’evento WINDOW_CLOSING causato dal clic sul pulsante di chiusura della finestra, l’applicazione viene chiusa.
5.2.2.2.5. Conclusione
Il codice della classe della finestra è diverso da quello presentato nell’esempio all’inizio del capitolo. Se utilizzassimo uno strumento di generazione Java diverso da JBuilder, avremmo senza dubbio un codice ancora diverso. In pratica, accetteremo il codice prodotto da JBuilder per costruire la finestra, in modo da concentrarci esclusivamente sulla scrittura dei gestori di eventi dell’interfaccia grafica.
5.2.3. Disegnare un'interfaccia grafica
5.2.3.1. Un esempio
Nell’esempio precedente non avevamo inserito alcun componente nella finestra. Costruiamo ora una finestra con un pulsante, un’etichetta e un campo di immissione:

I campi sono i seguenti:
n° | nome | tipo | ruolo |
1 | lblSaisie | JLabel | una denominazione |
2 | txtSaisie | JTextField | un campo di immissione |
3 | cmdAfficher | JButton | per visualizzare in una finestra di dialogo il contenuto del campo di immissione txtSaisie |
Procedendo come nel progetto precedente, create il progetto interface2.jpr senza inserire per il momento alcun componente nella finestra.

Nella finestra sopra riportata, selezionate la classe interface2.java. A destra di questa finestra si trova un raccoglitore a schede:

La scheda Source consente di accedere al codice sorgente della classe interface2.java. La scheda Conception consente di costruire visivamente la finestra. Selezionate questa scheda. Davanti a voi avete il contenitore della finestra, che accoglierà i componenti che vi trascinerete. Per il momento è vuoto. Nella finestra a sinistra è mostrata la struttura della classe:

this | rappresenta la finestra |
contentPane | il contenitore in cui verranno inseriti i componenti, nonché la modalità di disposizione di tali componenti all'interno del contenitore (BorderLayout per impostazione predefinita) |
borderLayout1 | un'istanza del gestore di formattazione |
Selezionare l'oggetto this. La finestra delle proprietà apparirà quindi sulla destra:

Alcune di queste proprietà meritano di essere segnalate:
background | per impostare il colore di sfondo della finestra |
foreground | per impostare il colore degli elementi grafici nella finestra |
JMenuBar | per associare un menu alla finestra |
title | per assegnare un titolo alla finestra |
resizable | per impostare il tipo di finestra |
font | per impostare il carattere dei testi nella finestra |
Con l'oggetto this ancora selezionato, è possibile ridimensionare il contenitore visualizzato sullo schermo trascinando i punti di ancoraggio situati attorno al contenitore:

Ora siamo pronti per inserire dei componenti nel contenitore sopra indicato. Prima però, cambieremo il gestore di formattazione. Selezionare l’oggetto contentPane nella finestra della struttura:

Quindi, nella finestra delle proprietà di questo oggetto, selezionate la proprietà layout e scegliete, tra i valori disponibili, il valore null:

L'assenza di un gestore di formattazione ci consentirà di posizionare liberamente i componenti all'interno del contenitore. È ora il momento di selezionarli.
Quando è selezionato il riquadro Conception, i componenti sono disponibili in una cartella a schede nella parte superiore della finestra di progettazione:

Per costruire l’interfaccia grafica, disponiamo dei componenti swing (1) e dei componenti awt (2). In questo caso utilizzeremo i componenti swing. Nella barra dei componenti sopra riportata, selezionate un componente JLabel (3), un componente JTextField (4) e un componente JButton (5) e posizionateli nel contenitore della finestra di progettazione.

Ora personalizziamo ciascuno di questi 3 componenti:
- l’etichetta (JLabel) jLabel1
Selezionate il componente per visualizzarne la finestra delle proprietà. In essa, modificate le seguenti proprietà: name: lblSaisie, text: Inserimento
- il campo di immissione (JTextField) jTextfield1
Selezionare il componente per visualizzarne la finestra delle proprietà. In essa, modificare le seguenti proprietà: name: txtSaisie, text: lasciare vuoto
- il pulsante (JButton): nome: cmdAfficher, testo: Visualizza
Ora abbiamo la seguente finestra:

e la seguente struttura:

Possiamo eseguire (F9) il nostro progetto per avere una prima anteprima della finestra in azione:

Chiudete la finestra. Resta da scrivere la procedura associata al clic sul pulsante Afficher. Selezionate il pulsante per accedere alla sua finestra delle proprietà. Questa presenta due schede: propriétés e événements. Scegliete événements.

La colonna di sinistra della finestra elenca gli eventi possibili relativi al pulsante. Un clic su un pulsante corrisponde all’evento actionPerformed. La colonna di destra contiene il nome della procedura chiamata quando si verifica l’evento corrispondente. Fare clic sulla cella a destra dell’evento actionPerformed:

Jbuilder genera un nome predefinito per ogni gestore di eventi nel formato nomComposant_nomEvénement, in questo caso cmdAfficher_actionPerformed. È possibile cancellare il nome predefinito e inserirne uno diverso. Per accedere al codice del gestore cmdAfficher_actionPerformed è sufficiente fare doppio clic sul suo nome qui sopra. Si passa quindi automaticamente al riquadro del codice sorgente della classe, posizionato sullo scheletro del codice del gestore di eventi:
Non resta che completare questo codice. In questo caso, vogliamo visualizzare una finestra di dialogo contenente il contenuto del campo txtSaisie:
void cmdAfficher_actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(this, "texte saisi="+txtSaisie.getText(),
"Vérification de la saisie",JOptionPane.INFORMATION_MESSAGE);
}
JOptionPane è una classe della libreria javax.swing. Consente di visualizzare messaggi accompagnati da un’icona o di richiedere informazioni all’utente. In questo caso, utilizziamo un metodo statico della classe:

parentComponent | l’oggetto contenitore “genitore” della finestra di dialogo: in questo caso this. |
messaggio | un oggetto da visualizzare. In questo caso il contenuto del campo di immissione |
titolo | il titolo della finestra di dialogo |
messageType | il tipo di messaggio da visualizzare. Determina l'icona che verrà visualizzata nella casella accanto al messaggio. Valori possibili: INFORMATION_MESSAGE, QUESTION_MESSAGE, ERROR_MESSAGE, WARNING_MESSAGE, PLAIN_MESSAGE |
Eseguiamo la nostra applicazione (F9):


5.2.3.2. Il codice della classe della finestra
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.beans.*;
import javax.swing.event.*;
public class interface2 extends JFrame {
JPanel contentPane;
JLabel lblSaisie = new JLabel();
JTextField txtSaisie = new JTextField();
JButton cmdAfficher = new JButton();
/**Creare il frame*/
public interface2() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inizializzare il componente*/
private void jbInit() throws Exception {
lblSaisie.setText("Saisie");
lblSaisie.setBounds(new Rectangle(25, 23, 71, 21));
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(null);
this.setSize(new Dimension(304, 129));
this.setTitle("Saisies & boutons - 1");
txtSaisie.setBounds(new Rectangle(120, 21, 138, 24));
cmdAfficher.setText("Afficher");
cmdAfficher.setBounds(new Rectangle(111, 77, 77, 20));
cmdAfficher.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
cmdAfficher_actionPerformed(e);
}
});
contentPane.add(lblSaisie, null);
contentPane.add(txtSaisie, null);
contentPane.add(cmdAfficher, null);
}
/**Sostituito, in modo da poter uscire quando la finestra viene chiusa*/
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
}
void cmdAfficher_actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(this, "texte saisi="+txtSaisie.getText(), "Vérification de la saisie",JOptionPane.INFORMATION_MESSAGE);
}
}
5.2.3.2.1. Gli attributi
JPanel contentPane;
JLabel lblSaisie = new JLabel();
JTextField txtSaisie = new JTextField();
JButton cmdAfficher = new JButton();
Si trovano il contenitore dei componenti di tipo JPanel e i tre componenti.
5.2.3.2.2. Il produttore
/**Creare il frame*/
public interface2() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inizializzare il componente*/
private void jbInit() throws Exception {
lblSaisie.setText("Saisie");
lblSaisie.setBounds(new Rectangle(25, 23, 71, 21));
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(null);
this.setSize(new Dimension(304, 129));
this.setTitle("Saisies & boutons - 1");
txtSaisie.setBounds(new Rectangle(120, 21, 138, 24));
cmdAfficher.setText("Afficher");
cmdAfficher.setBounds(new Rectangle(111, 77, 77, 20));
cmdAfficher.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
cmdAfficher_actionPerformed(e);
}
});
contentPane.add(lblSaisie, null);
contentPane.add(txtSaisie, null);
contentPane.add(cmdAfficher, null);
}
Il costruttore interface2 è simile al costruttore della precedente interfaccia grafica analizzata. Le differenze si riscontrano nel metodo jbInit: il codice di costruzione della finestra dipende dai componenti che vi sono stati inseriti. È possibile riutilizzare il codice di jbInit inserendovi i propri commenti:
private void jbInit() throws Exception {
// la finestra stessa (dimensioni, titolo)
this.setSize(new Dimension(304, 129));
this.setTitle("Saisies & boutons - 1");
// il contenitore dei componenti
contentPane = (JPanel) this.getContentPane();
// nessun gestore di formattazione per questo contenitore
contentPane.setLayout(null);
// l'etichetta lblSaisie (testo, posizione, dimensione)
lblSaisie.setText("Saisie");
lblSaisie.setBounds(new Rectangle(25, 23, 71, 21));
// il campo di immissione (posizione, dimensione)
txtSaisie.setBounds(new Rectangle(120, 21, 138, 24));
// il pulsante Visualizza (etichetta, posizione, dimensione)
cmdAfficher.setText("Afficher");
cmdAfficher.setBounds(new Rectangle(111, 77, 77, 20));
// il gestore degli eventi del pulsante
cmdAfficher.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
cmdAfficher_actionPerformed(e);
}
});
// aggiunta dei 3 componenti al contenitore
contentPane.add(lblSaisie, null);
contentPane.add(txtSaisie, null);
contentPane.add(cmdAfficher, null);
}//jbInit
Si notino due punti:
- questo codice avrebbe potuto essere scritto a mano. Ciò significa che è possibile fare a meno di JBuilder per creare un'interfaccia grafica.
- il modo in cui è impostato il gestore di eventi del pulsante cmdAfficher. Il gestore di eventi del componente cmdAfficher avrebbe potuto essere dichiarato tramite cmdAfficher.addActionListener(new gestore()) dove gestionnaire sarebbe una classe con un metodo pubblico actionPerformed incaricato di gestire il clic sul pulsante Afficher. In questo caso, JBuilder utilizza come gestore un'istanza di una classe anonima:
new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
cmdAfficher_actionPerformed(e);
}
Viene creata una nuova istanza dell'interfaccia ActionListener con il relativo metodo actionPerformed definito immediatamente dopo. Quest'ultimo si limita a chiamare un metodo della classe interface2. Tutto ciò non è altro che un espediente per definire, nella stessa classe della finestra, le procedure di gestione degli eventi dei componenti di tale finestra. Si potrebbe procedere in altro modo:
il che fa sì che il metodo actionPerformed venga cercato in this, ovvero nella classe della finestra. Questo secondo metodo sembra più semplice, ma il primo presenta un vantaggio: consente di avere gestori diversi per pulsanti diversi, mentre il secondo metodo non lo permette. In quest'ultimo caso, infatti, l'unico metodo actionPeformed deve gestire i clic di pulsanti diversi e quindi deve prima identificare quale di essi ha generato l'evento prima di iniziare a funzionare.
5.2.3.2.3. I gestori di eventi
Ritroviamo quelli già studiati:
/**Sostituito, in modo da poter uscire quando la finestra viene chiusa*/
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
}
// clic sul pulsante Visualizza
void cmdAfficher_actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(this, "texte saisi="+txtSaisie.getText(), "Vérification de la saisie",JOptionPane.INFORMATION_MESSAGE);
}
5.2.3.3. Conclusion
Dai due progetti esaminati, possiamo concludere che, una volta realizzata l’interfaccia grafica con JBuilder, il compito dello sviluppatore consiste nello scrivere i gestori degli eventi che desidera gestire per tale interfaccia grafica.
5.2.4. Cercare aiuto
Con Java, spesso si ha bisogno di aiuto, soprattutto a causa dell’elevatissimo numero di classi disponibili. Di seguito forniamo alcune indicazioni per trovare assistenza su una classe. Selezionate l’opzione Aiuto/Argomenti di aiuto dal menu.

La schermata di aiuto presenta generalmente due finestre:
- quella a sinistra, in cui si specifica ciò che si sta cercando. Presenta tre schede: Sommaire, Index e Chercher.
- quella a destra, che mostra il risultato della ricerca
È disponibile una guida su come utilizzare la guida di JBuilder. Selezionate nella guida di JBuilder l’opzione Guida/Utilizzo della guida. Vi verrà quindi spiegato come utilizzare la guida. Vi verranno illustrate, ad esempio, le diverse componenti del visualizzatore della guida:

Esaminiamo più da vicino le pagine Sommaire e Index.
5.2.4.1. Guida: Indice

5.2.4.1.1. Indice: Introduzione a Java
Qui si trovano gli elementi di base di Java, ma non solo, come dimostra l’elenco degli argomenti trattati in questa opzione:

5.2.4.1.2. Indice: Tutorial
Se selezioniamo l’opzione Tutorial dall’indice sopra riportato, la finestra a destra ci presenta un elenco dei tutorial disponibili:

I tutorial di base sono particolarmente utili per iniziare a familiarizzare con JBuilder. Ne esistono molti altri oltre a quelli presentati sopra e, quando si desidera sviluppare un’applicazione, può essere utile verificare in anticipo se non ci sia un tutorial che possa aiutarci.
5.2.4.1.3. Indice: JDK
Selezionando l’opzione Java 2 JDK 1.3, si ha accesso a tutte le librerie di JDK. In genere non è qui che bisogna cercare se si hanno bisogno di informazioni su una classe specifica e non si sa in quale libreria si trovi. D’altra parte, questa opzione è utile se si desidera avere una visione d’insieme delle librerie di Java.
5.2.4.2. Guida: Indice
Selezionate la scheda Indice nella finestra a sinistra della guida. Questa opzione consente, ad esempio, di trovare informazioni su una classe. Supponiamo, ad esempio, che vogliate conoscere i metodi dei campi di immissione swing e JTextField. Digitate JTextField nel campo di immissione del testo da cercare:
![]()
La guida restituirà le voci dell’indice che iniziano con il testo digitato:

A questo punto basta fare doppio clic sulla voce che vi interessa, in questo caso JTextField class. La guida relativa a questa classe verrà quindi visualizzata nella finestra a destra:

Viene quindi fornita una descrizione completa della classe.
5.2.5. Alcuni componenti Swing
Presentiamo ora diverse applicazioni che utilizzano i componenti swing più comuni, al fine di scoprirne i principali metodi e proprietà. Per ogni applicazione, presentiamo l'interfaccia grafica e il codice rilevante, in particolare quello dei gestori di eventi.
5.2.5.1. Componenti JLabel e JTextField
Abbiamo già incontrato questi due componenti. JLabel è un componente di testo e JTextField un componente campo di immissione. I loro due metodi principali sono
String getText() | per ottenere il contenuto del campo di immissione o il testo dell’etichetta |
void setText(String unTexte) | per inserire unTexte nel campo o nell’etichetta |
Gli eventi solitamente utilizzati per JTextField sono i seguenti:
actionPerformed | segnala che l'utente ha confermato (tasto Invio) il testo inserito |
caretUpdate | segnala che l'utente ha spostato il cursore di inserimento |
inputMethodChanged | segnala che l'utente ha modificato il campo di immissione |
Ecco un esempio che utilizza l'evento caretUpdate per monitorare le modifiche apportate a un campo di immissione:

n. | tipo | nome | ruolo |
1 | JTextField | txtSaisie | campo di immissione |
2 | JTextField | txtControle | visualizza il testo di 1 in tempo reale |
3 | JButton | cmdEffacer | per cancellare i campi 1 e 2 |
4 | JButton | cmdQuitter | per uscire dall'applicazione |
Il codice pertinente di questa applicazione è il seguente:
import java.awt.*;
....
public class Cadre1 extends JFrame {
JPanel contentPane;
JTextField txtSaisie = new JTextField();
JLabel jLabel1 = new JLabel();
JLabel jLabel2 = new JLabel();
JTextField txtControle = new JTextField();
JButton CmdEffacer = new JButton();
JButton CmdQuitter = new JButton();
/**Creare il frame*/
public Cadre1() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inizializzare il componente*/
private void jbInit() throws Exception {
....
txtSaisie.addCaretListener(new javax.swing.event.CaretListener() {
public void caretUpdate(CaretEvent e) {
txtSaisie_caretUpdate(e);
}
});
...
CmdEffacer.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
CmdEffacer_actionPerformed(e);
}
});
...
CmdQuitter.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
CmdQuitter_actionPerformed(e);
}
});
....
}
/**Sostituito, così possiamo uscire quando la finestra è chiusa*/
protected void processWindowEvent(WindowEvent e) {
...
}
void txtSaisie_caretUpdate(CaretEvent e) {
// il cursore di immissione si è spostato
txtControle.setText(txtSaisie.getText());
}
void CmdQuitter_actionPerformed(ActionEvent e) {
// si esce dall'applicazione
System.exit(0);
}
void CmdEffacer_actionPerformed(ActionEvent e) {
// si cancella il contenuto del campo di immissione
txtSaisie.setText("");
}
}
Ecco un esempio di esecuzione:

5.2.5.2. componente JComboBox


Un componente JComboBox è un menu a tendina abbinato a un campo di immissione: l'utente può scegliere un elemento da (2) oppure digitare del testo in (1). Per impostazione predefinita, i componenti JComboBox non sono modificabili. Per renderli modificabili, è necessario richiamare esplicitamente il metodo setEditable(true). Per scoprire la classe JComboBox, digitare JComboBox nell'indice della guida.
L'oggetto JComboBox può essere creato in diversi modi:
new JComboBox() | crea un menu a tendina vuoto |
new JComboBox (Object[] items) | crea un menu a discesa contenente un array di oggetti |
new JComboBox(Vector items) | idem con un vettore di oggetti |
Potrebbe sorprendere che un menu a discesa possa contenere oggetti, mentre solitamente contiene stringhe di caratteri. Dal punto di vista visivo, sarà proprio così. Se un JComboBox contiene un oggetto obj, visualizzerà la stringa obj.toString(). Ricordiamo che ogni oggetto dispone di un metodo toString ereditato dalla classe Object, che restituisce una stringa di caratteri «rappresentativa» dell’oggetto.
I metodi utili della classe JCombobox sono i seguenti:
void addItem(Object unObjet) | aggiunge un oggetto alla casella combinata |
int getItemCount() | restituisce il numero di elementi del menu a discesa |
Object getItemAt(int i) | restituisce l'oggetto n. i del menu a discesa |
void insertItemAt(Object unObjet, int i) | inserisce unObjet nella posizione i del menu a tendina |
int getSelectedIndex() | restituisce il numero dell'elemento selezionato nel menu a discesa |
Object getSelectedItem() | restituisce l'oggetto selezionato nel menu a discesa |
void setSelectedIndex(int i) | seleziona l'elemento i del menu a tendina |
void setSelectedItem(Object unObjet) | seleziona l'oggetto specificato nel menu a tendina |
void removeAllItems() | svuota il menu a tendina |
void removeItemAt(int i) | rimuove l'elemento n. i dal menu a tendina |
void removeItem(Object unObjet) | rimuove l'oggetto specificato dal menu a discesa |
void setEditable(boolean val) | rende la casella combinata modificabile (val=true) o non modificabile (val=false) |
Quando si seleziona un elemento dall'elenco a discesa, si verifica l'evento actionPerformed, che può quindi essere utilizzato per ricevere una notifica del cambiamento di selezione nel menu a discesa. Nell'applicazione seguente, utilizziamo questo evento per visualizzare l'elemento che è stato selezionato nell'elenco.

Presentiamo solo il codice rilevante della finestra.
public class Cadre1 extends JFrame {
JPanel contentPane;
JComboBox jComboBox1 = new JComboBox();
JLabel jLabel1 = new JLabel();
/**Creazione del riquadro*/
public Cadre1() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
// elaborazione - si compila la casella combinata
String[] infos={"un","deux","trois","quatre"};
for(int i=0;i<infos.length;i++)
jComboBox1.addItem(infos[i]);
}
/**Inizializza il componente*/
private void jbInit() throws Exception {
....
jComboBox1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
jComboBox1_actionPerformed(e);
}
});
....
}
void jComboBox1_actionPerformed(ActionEvent e) {
// è stato selezionato un nuovo elemento - visualizzarlo
JOptionPane.showMessageDialog(this,jComboBox1.getSelectedItem(),
"actionPerformed",JOptionPane.INFORMATION_MESSAGE);
}
}
5.2.5.3. componente JList
Il componente Swing JList è più complesso rispetto al suo omologo della libreria awt. Vi sono due differenze significative:
- il contenuto della lista è gestito da un oggetto diverso dalla lista stessa. In questo caso utilizzeremo un oggetto DefaultListModel, che si utilizza come un Vector ma che, inoltre, avvisa l’oggetto JList non appena il suo contenuto cambia, in modo che anche la visualizzazione dell’elenco si aggiorni di conseguenza.
- Per impostazione predefinita, l’elenco non è a scorrimento. È necessario inserire l’elenco in un contenitore ScrollPane che ne consenta lo scorrimento.
Nel codice sorgente, la definizione di un elenco può essere effettuata nel modo seguente:
// il vettore dei valori dell'elenco
DefaultlistModel valeurs=new DefaultListModel();
// l'elenco stesso a cui si associa il vettore dei suoi valori
JList jList1 = new JList(valeurs);
// il contenitore a scorrimento in cui si inserisce l'elenco per ottenere un elenco a scorrimento
JScrollPane jScrollPane1 = new JScrollPane(jList1);
Per includere l'elenco jList1 nel contenitore jScrollPane1, il codice generato da JBuilder procede in modo diverso:
- dichiarazione del contenitore negli attributi della finestra
- poi, nel codice di jbInit, l'elenco viene associato al contenitore
Per aggiungere valori all’elenco JList1 sopra riportato, è sufficiente aggiungerli al relativo vettore di valori valeurs:
e si ottiene quindi la seguente finestra:

Come è strutturata questa interfaccia?
- si seleziona un componente JScrollPane nella pagina «Contenitori Swing» dei componenti e lo si trascina nella finestra, regolandone le dimensioni in base alle proprie esigenze
- si seleziona un componente JList nella pagina "Swing" dei componenti e lo si trascina nel contenitore JScrollPane, occupandone l'intero spazio.
Il codice generato da JBuilder deve essere leggermente modificato per ottenere il codice seguente:
public class interfaceAppli extends JFrame {
JPanel contentPane;
JLabel jLabel1 = new JLabel();
DefaultListModel valeurs=new DefaultListModel();
JList jList1 = new JList(valeurs);
JScrollPane jScrollPane1 = new JScrollPane();
JLabel jLabel2 = new JLabel();
/**Costruire il frame*/
public interfaceAppli() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
// elaborazione
// si include l'elenco nel scrollPane
// inizializzazione elenco
for(int i=0;i<10;i++)
valeurs.addElement(""+i);
}
/**Inizializzazione del componente*/
private void jbInit() throws Exception {
....
// l'elenco jList1 è associato al contenitore jcrollPane1
jScrollPane1.getViewport().add(jList1, null);
}
/**Sostituito, in modo da poter uscire quando la finestra viene chiusa*/
protected void processWindowEvent(WindowEvent e) {
....
}
}
Scopriamo ora i principali metodi della classe JList cercando JList nell'indice della guida. L'oggetto JList può essere creato in diversi modi:

Un metodo semplice è quello che abbiamo utilizzato: creare un DefaultListModel V vuoto e poi associarlo alla lista da creare tramite new JList(V). Il contenuto della lista non è gestito dall’oggetto JList, ma dall’oggetto che contiene i valori della lista. Se il contenuto è stato creato utilizzando un oggetto DefaultListModel basato sulla classe Vector, per aggiungere, inserire ed eliminare elementi dall’elenco si potranno utilizzare i metodi della classe Vector. Un elenco può prevedere la selezione singola o multipla. Ciò viene stabilito dal metodo setSelectionMode:

È possibile conoscere la modalità di selezione corrente con getSelectionMode:
![]()
È possibile ottenere l’elemento o gli elementi selezionati tramite i seguenti metodi:

È possibile associare un vettore di valori a un elenco utilizzando il costruttore JList(DefaultListModel). Viceversa, è possibile ottenere l'oggetto DefaultListModel da un elenco JList tramite:

Ora sappiamo abbastanza per scrivere la seguente applicazione:

I componenti di questa finestra sono i seguenti:
n. | tipo | nome | funzione |
1 | JTextField | txtSaisie | campo di immissione |
2 | JList | jList1 | elenco contenuto in un contenitore jScrollPane1 |
3 | JList | jList2 | elenco contenuto in un contenitore jScrollPane2 |
4 | JButton | cmd1To2 | trasferisce gli elementi selezionati dall'elenco 1 all'elenco 2 |
5 | JButton | cmd2To1 | esegue l'operazione inversa |
6 | JButton | cmdRaz1 | svuota l'elenco 1 |
7 | JButton | cmdRaz2 | svuota l'elenco 2 |
L'utente digita del testo nel campo (1) e lo conferma. A questo punto si verifica l'evento actionPerformed sul campo di immissione, che viene utilizzato per aggiungere il testo digitato all'elenco 1. Ecco il codice utile per questa prima funzione:
public class interfaceAppli extends JFrame {
JPanel contentPane;
JLabel jLabel1 = new JLabel();
JLabel jLabel2 = new JLabel();
JLabel jLabel3 = new JLabel();
JTextField txtSaisie = new JTextField();
JButton cmd1To2 = new JButton();
JButton cmd2To1 = new JButton();
DefaultListModel v1=new DefaultListModel();
DefaultListModel v2=new DefaultListModel();
JList jList1 = new JList(v1);
JList jList2 = new JList(v2);
JScrollPane jScrollPane1 = new JScrollPane();
JScrollPane jScrollPane2 = new JScrollPane();
JButton cmdRaz1 = new JButton();
JButton cmdRaz2 = new JButton();
JLabel jLabel4 = new JLabel();
/**Creare il frame*/
public interfaceAppli() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}//interfaceAppli
/**Inizializzare il componente*/
private void jbInit() throws Exception {
...
txtSaisie.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
txtSaisie_actionPerformed(e);
}
});
...
// Jlist1 viene inserito nel contenitore jScrollPane1
jScrollPane1.getViewport().add(jList1, null);
// Jlist2 viene inserito nel contenitore jScrollPane2
jScrollPane2.getViewport().add(jList2, null);
...
}
/**Sostituito, in modo da poter uscire quando la finestra viene chiusa*/
protected void processWindowEvent(WindowEvent e) {
...
}
void txtSaisie_actionPerformed(ActionEvent e) {
// il testo inserito è stato convalidato
// viene recuperato senza gli spazi iniziali e finali
String texte=txtSaisie.getText().trim();
// se è vuoto, non lo vogliamo
if(texte.equals("")){
// messaggio di errore
JOptionPane.showMessageDialog(this,"Vous devez taper un texte",
"Erreur",JOptionPane.WARNING_MESSAGE);
// fine
return;
}//if
// se non è vuoto, lo si aggiunge ai valori dell'elenco 1
v1.addElement(texte);
// e si svuota il campo di immissione
txtSaisie.setText("");
}/// txtSaisie_actionperformed
}//classe
Il codice per trasferire gli elementi selezionati da un elenco all'altro è il seguente:
void cmd1To2_actionPerformed(ActionEvent e) {
// trasferimento degli elementi selezionati dall'elenco 1 all'elenco 2
transfert(jList1,jList2);
}//cmd1To2
void cmd2To1_actionPerformed(ActionEvent e) {
// trasferimento degli elementi selezionati in jList2 verso jList1
transfert(jList2,jList1);
}//cmd2TO1
private void transfert(JList L1, JList L2){
// trasferimento degli elementi selezionati dall'elenco 1 all'elenco 2
// si recupera la tabella degli indici degli elementi selezionati in L1
int[] indices=L1.getSelectedIndices();
// c'è qualcosa da fare?
if (indices.length==0) return;
// si recuperano i valori da L1
DefaultListModel v1=(DefaultListModel)L1.getModel();
// e quelli di L2
DefaultListModel v2=(DefaultListModel)L2.getModel();
for(int i=indices.length-1;i>=0;i--){
// si aggiungono a L2 i valori selezionati in L1
v2.addElement(v1.elementAt(indices[i]));
// gli elementi di L1 copiati in L2 devono essere eliminati da L1
v1.removeElementAt(indices[i]);
}//per
}//trasferimento
Il codice associato ai pulsanti Raz è semplicissimo:
void cmdRaz1_actionPerformed(ActionEvent e) {
// svuota elenco 1
v1.removeAllElements();
}//comando Raz1
void cmdRaz2_actionPerformed(ActionEvent e) {
// svuota lista 2
v2.removeAllElements();
}///cmd Raz2
5.2.5.4. Caselle di selezione JCheckBox, pulsanti di opzione JButtonRadio
Ci proponiamo di scrivere la seguente applicazione:

I componenti della finestra sono i seguenti:
n. | tipo | nome | funzione |
1 | JButtonRadio | jButtonRadio1 jButtonRadio2 jButtonRadio3 | 3 pulsanti di opzione appartenenti al gruppo buttonGroup1 |
2 | JCheckBox | jCheckBox1 jCheckBox2 jCheckBox3 | 3 caselle di selezione |
3 | JList | jList1 | un elenco in un contenitore jScrollPane1 |
4 | ButtonGroup | buttonGroup1 | componente non visibile - serve a raggruppare i 3 pulsanti di opzione in modo che, quando uno di essi si attiva, gli altri si disattivino. |
Un gruppo di pulsanti di opzione può essere creato nel modo seguente:
- si posizionano i singoli pulsanti di opzione senza preoccuparsi di raggrupparli
- si inserisce nel contenitore un componente Swing ButtonGroup. Questo componente è non visibile. Non compare quindi nel designer della finestra. Compare tuttavia nella sua struttura:

Come si vede sopra, nel ramo Autre sono riportati gli attributi non visivi della finestra. Una volta creato un gruppo di pulsanti di opzione, è possibile associarvi ciascuno dei pulsanti di opzione. A tal fine, selezionare le proprietà del pulsante di opzione:

e nella proprietà buttonGroup del pulsante di opzione si inserisce il nome del gruppo in cui si desidera inserire il pulsante di opzione, in questo caso buttonGroup1. Si ripete questa operazione per tutti e 3 i pulsanti di opzione.
Il metodo principale per i pulsanti di opzione e le caselle di controllo è il metodo isSelected(), che indica se la casella o il pulsante è selezionato. Il testo associato al componente può essere recuperato con getText() e impostato con setText(String unTexte). La casella di controllo o il pulsante di opzione può essere selezionato con il metodo setSelected(boolean value).
Quando si fa clic su un pulsante di opzione o su una casella di controllo, viene attivato l’evento actionPerformed. Nel codice seguente, utilizziamo questo evento per monitorare le modifiche dei valori dei pulsanti di opzione e delle caselle di controllo:
public class interfaceAppli extends JFrame {
JPanel contentPane;
JRadioButton jRadioButton1 = new JRadioButton();
JRadioButton jRadioButton2 = new JRadioButton();
JRadioButton jRadioButton3 = new JRadioButton();
JCheckBox jCheckBox1 = new JCheckBox();
JCheckBox jCheckBox2 = new JCheckBox();
JCheckBox jCheckBox3 = new JCheckBox();
ButtonGroup buttonGroup1 = new ButtonGroup();
JScrollPane jScrollPane1 = new JScrollPane();
DefaultListModel valeurs=new DefaultListModel();
JList jList1 = new JList(valeurs);
/**Costruire il frame*/
public interfaceAppli() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inizializzare il componente*/
private void jbInit() throws Exception {
jRadioButton1.setSelected(true);
jRadioButton1.setText("un");
jRadioButton1.setBounds(new Rectangle(57, 31, 49, 23));
jRadioButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
afficheRadioButtons(e);
}
});
jRadioButton2.setBounds(new Rectangle(113, 30, 49, 23));
jRadioButton2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
afficheRadioButtons(e);
}
});
jRadioButton2.setText("deux");
jRadioButton3.setBounds(new Rectangle(168, 30, 49, 23));
jRadioButton3.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
afficheRadioButtons(e);
}
});
jRadioButton3.setText("trois");
// i pulsanti di opzione sono raggruppati
buttonGroup1.add(jRadioButton1);
buttonGroup1.add(jRadioButton2);
buttonGroup1.add(jRadioButton3);
// caselle di controllo
jCheckBox1.setText("A");
jCheckBox1.setBounds(new Rectangle(58, 69, 32, 17));
jCheckBox1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
afficheCases(e);
}
});
jCheckBox2.setBounds(new Rectangle(112, 69, 40, 17));
jCheckBox2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
afficheCases(e);
}
});
jCheckBox2.setText("B");
jCheckBox3.setText("C");
jCheckBox3.setBounds(new Rectangle(170, 69, 37, 17));
jCheckBox3.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
afficheCases(e);
}
});
....
}
/**Sostituito, in modo da poter uscire quando la finestra viene chiusa*/
protected void processWindowEvent(WindowEvent e) {
...
}
private void afficheRadioButtons(ActionEvent e){
// visualizza i valori dei 3 pulsanti di opzione
valeurs.addElement("boutons radio=("+jRadioButton1.isSelected()+","+
jRadioButton2.isSelected()+","+jRadioButton3.isSelected()+")");
}//afficheRadioButtons
void afficheCases(ActionEvent e) {
// visualizza i valori delle caselle di controllo
valeurs.addElement("cases à cocher=["+jCheckBox1.isSelected()+","+
jCheckBox2.isSelected()+","+jCheckBox3.isSelected()+")");
}//afficheCases
}//ordina
Ecco un esempio di esecuzione:

5.2.5.5. componente JScrollBar
Realizziamo la seguente applicazione:

n. | tipo | nome | ruolo |
1 | JScrollBar | jScrollBar1 | un variatore orizzontale |
2 | JScrollBar | jScrollBar2 | un variatore verticale |
3 | JTextField | txtvaleurHS | visualizza il valore del variatore orizzontale 1 - consente anche di impostare tale valore |
4 | JTextField | txtvaleurVS | visualizza il valore del variatore verticale 2 - consente anche di impostare tale valore |
- Un variatore JScrollBar consente all'utente di selezionare un valore all'interno di un intervallo di valori interi rappresentato dalla "banda" del variatore su cui si sposta un cursore.
- Per un variatore orizzontale, l’estremità sinistra rappresenta il valore minimo dell’intervallo, l’estremità destra il valore massimo, il cursore il valore attuale selezionato. Per un variatore verticale, il minimo è rappresentato dall’estremità superiore, il massimo dall’estremità inferiore. La coppia (min, max) è impostata di default su (0,100).
- Un clic sulle estremità del variatore fa variare il valore di un incremento (positivo o negativo) a seconda dell’estremità cliccata, denominata unitIncrement, che per impostazione predefinita è 1.
- Un clic su entrambi i lati del cursore fa variare il valore di un incremento (positivo o negativo) a seconda dell'estremità cliccata, denominata blockIncrement, il cui valore predefinito è 10.
- Questi cinque valori (min, max, valore, unitIncrement, blockIncrement) possono essere ricavati tramite i metodi getMinimum(), getMaximum(), getValue(), getUnitIncrement(), getBlockIncrement(), che restituiscono tutti un numero intero e possono essere impostati tramite i metodi setMinimum(int min), setMaximum(int max), setValue(int val), setUnitIncrement(int uInc), setBlockIncrement(int bInc)
Ci sono alcuni aspetti da tenere presenti nell’utilizzo dei componenti JScrollBar. Innanzitutto, si trovano nella barra dei componenti Swing:

Quando lo si trascina sul contenitore, per impostazione predefinita è verticale. È possibile renderlo orizzontale utilizzando la proprietà orientation riportata di seguito:

Nella finestra delle proprietà sopra riportata si vede che si ha accesso alle proprietà minimum, maximum, value, unitIncrement, blockIncrement del JScrollbar. È quindi possibile impostarle in fase di progettazione. Quando si posiziona una barra di scorrimento sul contenitore, la sua “fascia di variazione” non appare:

È possibile risolvere questo problema aggiungendo un bordo al componente. Ciò si ottiene tramite la proprietà border, che può assumere diversi valori:

Ecco, ad esempio, il risultato ottenuto con RaisedBevel:
![]()
Quando si clicca sull'estremità superiore di un cursore verticale, il suo valore diminuisce. Ciò può sorprendere l'utente medio, che normalmente si aspetta di vedere il valore "aumentare". Si risolve questo problema assegnando un valore negativo a unitIncrement e blockIncrement.
Come monitorare le variazioni di un cursore? Quando il suo valore cambia, si verifica l’evento adjustmentValueChanged. È sufficiente associare una procedura a questo evento per essere informati di ogni variazione del valore della barra di scorrimento.

Il codice utile della nostra applicazione è il seguente:
....
public class cadreAppli extends JFrame {
JPanel contentPane;
JScrollBar jScrollBar1 = new JScrollBar();
Border border1;
JTextField txtValeurHS = new JTextField();
JScrollBar jScrollBar2 = new JScrollBar();
JTextField txtValeurVS = new JTextField();
TitledBorder titledBorder1;
/**Crea il riquadro*/
public cadreAppli() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inizializza il componente*/
private void jbInit() throws Exception {
...
// un bordo per le barre di scorrimento
border1 = BorderFactory.createBevelBorder(BevelBorder.RAISED,Color.white,Color.white,new Color(134, 134, 134),new Color(93, 93, 93));
// nessun titolo lungo il bordo
titledBorder1 = new TitledBorder("");
jScrollBar1.setOrientation(JScrollBar.HORIZONTAL);
jScrollBar1.setBorder(BorderFactory.createRaisedBevelBorder());
jScrollBar1.setAutoscrolls(true);
jScrollBar1.setBounds(new Rectangle(37, 17, 218, 20));
jScrollBar1.addAdjustmentListener(new java.awt.event.AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
jScrollBar1_adjustmentValueChanged(e);
}
});
txtValeurHS.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
txtValeurHS_actionPerformed(e);
}
});
jScrollBar2.setBounds(new Rectangle(39, 51, 30, 27));
jScrollBar2.addAdjustmentListener(new java.awt.event.AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
jScrollBar2_adjustmentValueChanged(e);
}
});
jScrollBar2.setAutoscrolls(true);
jScrollBar2.setUnitIncrement(-1);
jScrollBar2.setBorder(BorderFactory.createRaisedBevelBorder());
txtValeurVS.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
txtValeurVS_actionPerformed(e);
}
});
......
}
/**Sostituito, così possiamo uscire quando la finestra viene chiusa*/
protected void processWindowEvent(WindowEvent e) {
...
}
void jScrollBar1_adjustmentValueChanged(AdjustmentEvent e) {
// il valore della barra di scorrimento 1 è cambiato
txtValeurHS.setText(""+jScrollBar1.getValue());
}
void jScrollBar2_adjustmentValueChanged(AdjustmentEvent e) {
// il valore della barra di scorrimento 2 è cambiato
txtValeurVS.setText(""+jScrollBar2.getValue());
}
void txtValeurHS_actionPerformed(ActionEvent e) {
// si imposta il valore della barra di scorrimento orizzontale
setValeur(jScrollBar1,txtValeurHS);
}
void txtValeurVS_actionPerformed(ActionEvent e) {
// si imposta il valore della barra di scorrimento verticale
setValeur(jScrollBar2,txtValeurVS);
}
private void setValeur(JScrollBar jS, JTextField jT){
// fissa il valore della barra di scorrimento jS con il testo del campo jT
int valeur=0;
try{
valeur=Integer.parseInt(jT.getText());
jS.setValue(valeur);
}
catch (Exception e){
// viene visualizzato l'errore
afficher(""+e);
}//try-catch
}//setValeur
void afficher(String message){
// visualizza un messaggio in una finestra
JOptionPane.showMessageDialog(this,message,"Menus",JOptionPane.INFORMATION_MESSAGE);
}//visualizza
}
Ecco un esempio di esecuzione:

5.2.5.6. componente JTextArea
Il componente JTextArea è un componente in cui è possibile inserire più righe di testo, a differenza del componente JTextField, in cui è possibile inserire solo una riga. Se questo componente viene inserito in un contenitore a scorrimento (JScrollPane), si ottiene un campo di immissione testo a scorrimento. Questo tipo di componente potrebbe essere presente, ad esempio, in un’applicazione di posta elettronica in cui il testo del messaggio da inviare verrebbe digitato in un componente JTextArea. I metodi più comuni sono String getText() per conoscere il contenuto della casella di testo, setText(String unTexte) per inserire unTexte nella casella di testo, append(String unTexte) per aggiungere unTexte al testo già presente nella casella di testo. Consideriamo la seguente applicazione:

n. | tipo | nome | ruolo |
1 | JTextArea | txtTexte | un campo di testo multilinea |
2 | JButton | cmdAfficher | visualizza il contenuto di 1 in una finestra di dialogo |
3 | JButton | cmdEffacer | cancella il contenuto di 1 |
4 | JTextField | txtAjout | testo aggiunto al testo di 1 quando viene confermato con il tasto Invio. |
5 | JScrollPane | jScrollPane1 | container a scorrimento in cui è stata inserita l'area di testo 1 per ottenere un'area di testo a scorrimento. |
Il codice da utilizzare è il seguente:
.....
public class cadreAppli extends JFrame {
JPanel contentPane;
JLabel jLabel1 = new JLabel();
JButton cmdAfficher = new JButton();
JScrollPane jScrollPane1 = new JScrollPane();
JTextArea txtTexte = new JTextArea();
JLabel jLabel2 = new JLabel();
JTextField txtAjout = new JTextField();
JButton cmdEffacer = new JButton();
/**Creare il frame*/
public cadreAppli() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inizializza il componente*/
private void jbInit() throws Exception {
cmdAfficher.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
cmdAfficher_actionPerformed(e);
}
});
txtAjout.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
txtAjout_actionPerformed(e);
}
});
cmdEffacer.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
cmdEffacer_actionPerformed(e);
}
});
.......
jScrollPane1.getViewport().add(txtTexte, null);
}
/**Sostituito, in modo da poter uscire quando la finestra viene chiusa*/
protected void processWindowEvent(WindowEvent e) {
........
}
void cmdAfficher_actionPerformed(ActionEvent e) {
// visualizza il contenuto di TextArea
afficher(txtTexte.getText());
}
void afficher(String message){
// visualizza un messaggio in una finestra di dialogo
JOptionPane.showMessageDialog(this,message,"Suivi",JOptionPane.INFORMATION_MESSAGE);
}// visualizza
void cmdEffacer_actionPerformed(ActionEvent e) {
txtTexte.setText("");
}//cmdEffacer_actionPerformed
void txtAjout_actionPerformed(ActionEvent e) {
// aggiungere testo
txtTexte.append(txtAjout.getText());
// cancellazione aggiunta
txtAjout.setText("");
}//
}
5.2.6. Eventi del mouse
Quando si disegna all'interno di un contenitore, è importante conoscere la posizione del mouse per, ad esempio, visualizzare un punto al momento del clic. Gli spostamenti del mouse generano eventi nel contenitore in cui si muove. Ecco, ad esempio, quelli offerti da JBuilder per un contenitore JPanel:

mouseClicked | clic del mouse |
mouseDragged | il mouse si sposta, tasto sinistro premuto |
mouseEntered | il mouse è appena entrato nell'area del contenitore |
mouseExited | il mouse ha appena lasciato l'area del contenitore |
mouseMoved | il mouse si sta muovendo |
mousePressed | Pressione del tasto sinistro del mouse |
mouseReleased | Rilascio del tasto sinistro del mouse |
Ecco un programma che permette di comprendere meglio in quali momenti si verificano i diversi eventi del mouse:

n. | tipo | nome | ruolo |
1 | JTextField | txtPosition | per visualizzare la posizione del mouse nel contenitore (eventualmente MouseMoved) |
2 | JList | lstAffichage | per visualizzare gli eventi del mouse diversi da MouseMoved |
3 | JButton | cmdEffacer | per cancellare il contenuto di 2 |
Quando si esegue questo programma, ecco cosa si ottiene con un clic:

Gli eventi vengono impilati dall’alto nell’elenco. Pertanto, la schermata sopra riportata indica che un clic genera tre eventi, nell’ordine:
- MousePressed quando si preme il pulsante
- MouseReleased quando lo si rilascia
- MouseClicked, che indica che la successione dei due eventi precedenti viene considerata come un clic. Potrebbe trattarsi di un doppio clic. Tuttavia, l’informazione clickCount=1 sopra riportata indica che si tratta di un semplice clic.
Ora, se si preme il pulsante, si sposta il mouse e si rilascia il pulsante:

Qui si vedono i tre eventi:
- MousePressed quando si preme inizialmente il pulsante
- MouseDragged quando si sposta il mouse con il pulsante premuto
- MouseReleased quando si rilascia il pulsante
Nei due esempi sopra riportati, si nota che un evento del mouse porta con sé diverse informazioni, tra cui le coordinate (x, y) del mouse, ad esempio (408,65) nella prima riga sopra.
Proseguendo in questo modo, si scopre che l’evento MouseExited viene attivato non appena il mouse esce dal contenitore o passa su uno dei suoi componenti. In quest’ultimo caso, il contenitore riceve l’evento MouseExited e il componente l’evento MouseEntered. Si verificherà il contrario quando il mouse uscirà dal componente per tornare sul contenitore.
Cosa succede quando si esegue un doppio clic?

Si verificano esattamente gli stessi eventi di un clic singolo. L’unica differenza è che l’evento riporta l’informazione clickCount=2 (vedi sopra), a indicare che si è trattato effettivamente di un doppio clic.
Il codice utile di questa applicazione è il seguente:
public class Cadre1 extends JFrame {
JPanel contentPane;
JLabel jLabel1 = new JLabel();
JTextField txtPosition = new JTextField();
JScrollPane jScrollPane1 = new JScrollPane();
DefaultListModel valeurs=new DefaultListModel();
JList lstAffichage = new JList(valeurs);
JButton cmdEffacer = new JButton();
/**Costruire il frame*/
public Cadre1() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inizializzare il componente*/
private void jbInit() throws Exception {
contentPane.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
contentPane_mouseMoved(e);
}
public void mouseDragged(MouseEvent e) {
contentPane_mouseDragged(e);
}
});
contentPane.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseEntered(MouseEvent e) {
contentPane_mouseEntered(e);
}
public void mouseExited(MouseEvent e) {
contentPane_mouseExited(e);
}
public void mousePressed(MouseEvent e) {
contentPane_mousePressed(e);
}
public void mouseClicked(MouseEvent e) {
contentPane_mouseClicked(e);
}
public void mouseReleased(MouseEvent e) {
contentPane_mouseReleased(e);
}
});
cmdEffacer.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
cmdEffacer_actionPerformed(e);
}
});
jScrollPane1.getViewport().add(lstAffichage, null);
...............
}
/**Sostituito, in modo da poter uscire quando la finestra viene chiusa*/
protected void processWindowEvent(WindowEvent e) {
.........
}
void contentPane_mouseMoved(MouseEvent e) {
txtPosition.setText("("+e.getX()+","+e.getY()+")");
}
void contentPane_mouseDragged(MouseEvent e) {
afficher(e);
}
void contentPane_mouseEntered(MouseEvent e) {
afficher(e);
}
void afficher(MouseEvent e){
// visualizza l'evento e nell'elenco lstAffichage
valeurs.insertElementAt(e,0);
}
void contentPane_mouseExited(MouseEvent e) {
afficher(e);
}
void contentPane_mousePressed(MouseEvent e) {
afficher(e);
}
void contentPane_mouseClicked(MouseEvent e) {
afficher(e);
}
void contentPane_mouseReleased(MouseEvent e) {
afficher(e);
}
void cmdEffacer_actionPerformed(ActionEvent e) {
// cancella l'elenco
valeurs.removeAllElements();
}
}
5.2.7. Creare una finestra con menu
Vediamo ora come creare una finestra con menu utilizzando JBuilder. Creeremo la seguente finestra:


Create un nuovo progetto con una finestra vuota iniziale. Scegliete dall’elenco dei componenti “Contenitori Swing” il componente JMenuBar (cfr. figura 1 qui sotto) e trascinatelo sulla finestra in fase di progettazione.

Nella finestra di progettazione non appare nulla, ma il componente JMenuBar compare nel pannello della struttura della finestra:

Fare doppio clic sull’elemento jMenuBar1 sopra indicato per accedere al menu in modalità progettazione:

1 | inserire un elemento di menu |
2 | inserire un separatore |
3 | inserire un menu annidato |
4 | eliminare una voce di menu |
5 | disattivare una voce di menu |
6 | voce di menu da selezionare |
7 | invertire il pulsante di opzione |
Per creare la tua prima voce di menu, digita "Opzioni A" nella casella A qui sopra, poi sotto, nell'ordine: A1, A2, separatore, A3, A4.

Poi accanto:

Utilizzate lo strumento 3 per indicare che B3 è un sottomenu annidato.
Man mano che si procede con la progettazione del menu, la struttura logica della nostra finestra si evolve:

Se ora eseguiamo la nostra applicazione, vedremo una finestra vuota senza menu. Dobbiamo associare il menu creato alla nostra finestra. Per farlo, nella struttura della finestra, selezionate l'oggetto this:

A questo punto avrete accesso alle proprietà di this:

Una di queste è JMenuBar, che serve a definire il menu da associare alla finestra. Cliccate nella cella a destra di JMenuBar. Verranno quindi visualizzati tutti i menu creati. In questo caso, avremo solo jMenuBar1. Selezionatelo.
Avviare l’esecuzione dell’applicazione (F9):

Ora abbiamo un menu, ma le opzioni, per il momento, non fanno nulla. Le opzioni del menu vengono trattate come componenti: hanno proprietà ed eventi. Nella struttura del menu, selezionate l’opzione jMenuItem1:

A questo punto potrete accedere alle sue proprietà e ai suoi eventi:

Selezionate la pagina degli eventi e cliccate sulla cella a destra dell’evento actionPerformed: si tratta dell’evento che si verifica quando si clicca su un elemento del menu. Per impostazione predefinita vi viene proposta una procedura di elaborazione. Fate doppio clic su di essa per accedere al suo codice:

Scriveremo il seguente semplice codice:
void jMenuItem1_actionPerformed(ActionEvent e) {
afficher("L'option A1 a été sélectionnée");
}
void afficher(String message){
// visualizza un messaggio in una finestra di dialogo
JOptionPane.showMessageDialog(this,message,"Menus",JOptionPane.INFORMATION_MESSAGE);
}//visualizza
Eseguire l'applicazione e selezionare l'opzione A1 per visualizzare il seguente messaggio:

Il codice utile di questa applicazione è il seguente:
.....
public class Cadre1 extends JFrame {
JPanel contentPane;
BorderLayout borderLayout1 = new BorderLayout();
JMenuBar jMenuBar1 = new JMenuBar();
JMenu jMenu1 = new JMenu();
JMenuItem jMenuItem1 = new JMenuItem();
JMenuItem jMenuItem2 = new JMenuItem();
JMenuItem jMenuItem3 = new JMenuItem();
JMenuItem jMenuItem4 = new JMenuItem();
JMenu jMenu2 = new JMenu();
JMenuItem jMenuItem5 = new JMenuItem();
JMenuItem jMenuItem6 = new JMenuItem();
JMenu jMenu3 = new JMenu();
JMenuItem jMenuItem7 = new JMenuItem();
JMenuItem jMenuItem8 = new JMenuItem();
JMenuItem jMenuItem9 = new JMenuItem();
/**Crea il frame*/
public Cadre1() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inizializza il componente*/
private void jbInit() throws Exception {
// la finestra è associata a un menu
this.setJMenuBar(jMenuBar1);
jMenu1.setText("Options A");
jMenuItem1.setText("A1");
jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
jMenuItem1_actionPerformed(e);
}
});
jMenuItem2.setText("A2");
jMenuItem3.setText("A3");
jMenuItem4.setText("A4");
jMenu2.setText("Options B");
jMenuItem5.setText("B1");
jMenuItem6.setText("B2");
jMenu3.setText("B3");
jMenuItem7.setText("B31");
jMenuItem8.setText("B32");
jMenuItem9.setText("B4");
jMenuBar1.add(jMenu1);
jMenuBar1.add(jMenu2);
jMenu1.add(jMenuItem1);
jMenu1.add(jMenuItem2);
jMenu1.addSeparator();
jMenu1.add(jMenuItem3);
jMenu1.add(jMenuItem4);
jMenu2.add(jMenuItem5);
jMenu2.add(jMenuItem6);
jMenu2.add(jMenu3);
jMenu2.add(jMenuItem9);
jMenu3.add(jMenuItem7);
jMenu3.add(jMenuItem8);
}
/**Sostituito, in modo da poter uscire quando la finestra viene chiusa*/
protected void processWindowEvent(WindowEvent e) {
....
}
void jMenuItem1_actionPerformed(ActionEvent e) {
afficher("L'option A1 a été sélectionnée");
}
void afficher(String message){
// visualizza un messaggio in una finestra di dialogo
JOptionPane.showMessageDialog(this,message,"Menus",JOptionPane.INFORMATION_MESSAGE);
}//visualizza
}
5.3. Finestre di dialogo
5.3.1. Finestre di messaggio
Abbiamo già utilizzato la classe JOptionPane per visualizzare i messaggi. Pertanto, il codice seguente:
import javax.swing.*;
public class dialog1 {
public static void main(String arg[]){
JOptionPane.showMessageDialog(null,"Un message","Titre de la boîte",JOptionPane.INFORMATION_MESSAGE);
}
}
genera la visualizzazione della seguente finestra:

Quando si chiude questa finestra, essa scompare ma il thread di esecuzione in cui era in esecuzione non viene interrotto. Questo fenomeno normalmente non si verifica. Le finestre di dialogo vengono utilizzate all’interno di un’applicazione che, a un certo punto, utilizza un’istruzione System.exit(n) per arrestare tutti i thread. Ne terremo conto negli esempi che seguiranno, tutti basati sullo stesso modello. In DOS, l’applicazione può essere interrotta con Ctrl-C. Con JBuilder, si utilizzerà l’opzione Esegui/Reimposta il programma (Ctrl-F2). Inoltre, il primo argomento di showMessageDialog è in questo caso null. In genere non è così. Si tratta piuttosto di this o this, che indicano la finestra principale dell’applicazione.
5.3.2. Aspetto grafico
L’aspetto della finestra sopra riportata potrebbe essere diverso. È possibile configurarne l’aspetto tramite la classe javax.swing.UIManager. Quando abbiamo commentato il codice generato da JBuilder per la nostra prima finestra, abbiamo incontrato un’istruzione su cui non ci siamo soffermati:
Il metodo setLookAndFeel della classe UIManager (UI=Interfaccia utente) consente di definire l’aspetto delle interfacce grafiche. La classe UIManager dispone di un metodo che permette di conoscere le possibili «aspettative» per le interfacce:
static UIManager.LookAndFeelInfo[] | getInstalledLookAndFeels() |
Il metodo restituisce un array di elementi di tipo LookAndFeelInfo. Questa classe dispone di un metodo:
String | getClassName() |
che restituisce il nome della classe che "implementa" un determinato tema. Proviamo il seguente programma:
import javax.swing.*;
public class LookAndFeels {
// visualizza i look and feel disponibili
public static void main(String[] args) {
// Elenca i look and feel installati
UIManager.LookAndFeelInfo[] lf=UIManager.getInstalledLookAndFeels();
// visualizza
for(int i=0;i<lf.length;i++){
System.out.println(lf[i].getClassName());
}//per
}//main
}//classifica
Fornisce i seguenti risultati:
javax.swing.plaf.metal.MetalLookAndFeel
com.sun.java.swing.plaf.motif.MotifLookAndFeel
com.sun.java.swing.plaf.windows.WindowsLookAndFeel
Sembra quindi che ci siano tre "stili" diversi. Riprendiamo il nostro programma di visualizzazione dei messaggi provando i diversi stili possibili:
import javax.swing.*;
public class LookAndFeel2 {
// visualizza i look and feel disponibili
public static void main(String[] args) {
// elenco dei look and feel installati
UIManager.LookAndFeelInfo[] lf=UIManager.getInstalledLookAndFeels();
// visualizzazione
for(int i=0;i<lf.length;i++){
// gestore dell'aspetto
try{
UIManager.setLookAndFeel(lf[i].getClassName());
}catch(Exception ex){
System.err.println(ex.getMessage());
}//catch
// messaggio
JOptionPane.showMessageDialog(null,"Un message",lf[i].getClassName(),JOptionPane.INFORMATION_MESSAGE);
}//for
}//main
}//classe
L'esecuzione produce i seguenti risultati:
![]() | ![]() | ![]() |
corrispondenti, da destra a sinistra, ai "look" Metal, Motif, Windows.
5.3.3. Finestre di conferma
La classe JOptionPane dispone di un metodo showConfirmDialog per visualizzare finestre di conferma con i pulsanti Oui, Non, Annuler. Esistono diversi metodi showConfirmDialog sovrascritti. Ne esaminiamo uno:
static int | showConfirmDialog(Component parentComponent, Object message, String title, int optionType) |
parentComponent | il componente padre della finestra di dialogo. Spesso la finestra o il valore null |
message | il messaggio da visualizzare |
title | il titolo della finestra di dialogo |
optionType | JOptionPane.YES_NO_OPTION: pulsanti Sì, No JOptionPane.YES_NO_CANCEL_OPTION: pulsanti Sì, No, Annulla |
Il risultato restituito dal metodo è:
JOptionPane.YES_OPTION | l'utente ha cliccato su sì |
JOptionPane.NO_OPTION | l'utente ha cliccato su «No» |
JOptionPane.CANCEL_OPTION | l'utente ha cliccato su «Annulla» |
JOptionPane.CLOSED_OPTION | l'utente ha chiuso la finestra |
Ecco un esempio:
import javax.swing.*;
public class confirm1 {
public static void main(String[] args) {
// visualizza le finestre di conferma
int réponse;
affiche(JOptionPane.showConfirmDialog(null,"Voulez-vous continuer ?","Confirmation",JOptionPane.YES_NO_OPTION));
affiche(JOptionPane.showConfirmDialog(null,"Voulez-vous continuer ?","Confirmation",JOptionPane.YES_NO_CANCEL_OPTION));
}//main
private static void affiche(int réponse){
// indica quale tipo di risposta si è ricevuta
switch(réponse){
case JOptionPane.YES_OPTION :
System.out.println("Oui");
break;
case JOptionPane.NO_OPTION :
System.out.println("Non");
break;
case JOptionPane.CANCEL_OPTION :
System.out.println("Annuler");
break;
case JOptionPane.CLOSED_OPTION :
System.out.println("Fermeture");
break;
}//switch
}//display
}//classifica
![]() | ![]() |
Sulla console vengono visualizzati i messaggi Non e Annuler.
5.3.4. Campo di immissione
La classe JOptionPane offre anche la possibilità di effettuare un inserimento con il metodo showInputDialog. Anche in questo caso, esistono diversi metodi sovramodificati. Ne presentiamo uno:
static String | showInputDialog(Component parentComponent, Object message, String title, int messageType) |
Gli argomenti sono quelli già incontrati più volte. Il metodo restituisce la stringa digitata dall'utente. Ecco un esempio:
import javax.swing.*;
public class input1 {
public static void main(String[] args) {
// inserimento
System.out.println("Chaîne saisie ["+
JOptionPane.showInputDialog(null,"Quel est votre nom","Saisie du nom",JOptionPane.QUESTION_MESSAGE )
+ "]");
}//mano
}//classe
Visualizzazione della casella di immissione:

Visualizzazione della console:
5.4. Caselle di selezione
Passiamo ora ad esaminare alcune caselle di selezione predefinite in Java 2:
JFileChooser | casella di selezione che consente di selezionare un file nella struttura ad albero dei file |
JColorChooser | casella di selezione che consente di scegliere un colore |
5.4.1. Casella di selezione JFileChooser
Realizzeremo la seguente applicazione:

I controlli sono i seguenti:
N. | tipo | nome | ruolo |
0 | JScrollPane | jScrollPane1 | Container scorrevole per la casella di testo 1 |
1 | JTextArea all'interno di JScrollPane | txtTexte | testo digitato dall'utente o caricato da un file |
2 | JButton | btnSauvegarder | consente di salvare il testo di 1 in un file di testo |
3 | JButton | btnCharger | consente di caricare il contenuto di un file di testo in 1 |
4 | JButton | btnEffacer | cancella il contenuto di 1 |
Viene utilizzato un controllo non visivo: jFileChooser1. Questo viene prelevato dalla tavolozza dei contenitori Swing di JBuilder:

Inseriamo il componente nella finestra di progettazione, ma al di fuori del modulo. Appare nell’elenco dei componenti:

Ora riportiamo il codice del programma per averne una visione d’insieme:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.io.*;
public class dialogues extends JFrame {
// i componenti del riquadro
JPanel contentPane;
JButton btnSauvegarder = new JButton();
JButton btnCharger = new JButton();
JButton btnEffacer = new JButton();
JScrollPane jScrollPane1 = new JScrollPane();
JTextArea txtTexte = new JTextArea();
JFileChooser jFileChooser1 = new JFileChooser();
// i filtri dei file
javax.swing.filechooser.FileFilter filtreTxt = null;
//Costruire il frame
public dialogues() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
// altre inizializzazioni
moreInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
// moreInit
private void moreInit(){
// inizializzazioni alla creazione della finestra
// filtro *.txt
filtreTxt = new javax.swing.filechooser.FileFilter(){
public boolean accept(File f){
// si accetta f?
return f.getName().toLowerCase().endsWith(".txt");
}//accettato
public String getDescription(){
// descrizione del filtro
return "Fichiers Texte (*.txt)";
}//getDescription
};
// si aggiunge il filtro
jFileChooser1.addChoosableFileFilter(filtreTxt);
// si desidera anche il filtro per tutti i file
jFileChooser1.setAcceptAllFileFilterUsed(true);
// si imposta la directory di partenza della cartella FileChooser come directory corrente
jFileChooser1.setCurrentDirectory(new File("."));
}
//Inizializzare il componente
private void jbInit() throws Exception {
.......................
}
//Sostituito, così possiamo uscire quando la finestra viene chiusa
protected void processWindowEvent(WindowEvent e) {
......................
}
}
void btnCharger_actionPerformed(ActionEvent e) {
// selezione di un file tramite un oggetto JFileChooser
// si imposta il filtro iniziale
jFileChooser1.setFileFilter(filtreTxt);
// viene visualizzata la finestra di selezione
int returnVal = jFileChooser1.showOpenDialog(this);
// L'utente ha selezionato qualcosa?
if(returnVal == JFileChooser.APPROVE_OPTION) {
// si inserisce il file nel campo di testo
lireFichier(jFileChooser1.getSelectedFile());
}//if
}//btnCharger_actionPerformed
// lireFichier
private void lireFichier(File fichier){
// visualizza il contenuto del file di testo «fichier» nel campo di testo
// si cancella il campo di testo
txtTexte.setText("");
// alcuni dati
BufferedReader IN=null;
String ligne=null;
try{
// apertura del file in lettura
IN=new BufferedReader(new FileReader(fichier));
// si legge il file riga per riga
while((ligne=IN.readLine())!=null){
txtTexte.append(ligne+"\n");
}//while
// chiusura del file
IN.close();
}catch(Exception ex){
// si è verificato un errore
txtTexte.setText(""+ex);
}//catch
}
// cancella
void btnEffacer_actionPerformed(ActionEvent e) {
// si cancella la casella di testo
txtTexte.setText("");
}
// salva
void btnSauvegarder_actionPerformed(ActionEvent e) {
// salva il contenuto della casella di testo in un file
// imposta il filtro iniziale
jFileChooser1.setFileFilter(filtreTxt);
// viene visualizzata la finestra di selezione per il salvataggio
int returnVal = jFileChooser1.showSaveDialog(this);
// L'utente ha selezionato qualcosa?
if(returnVal == JFileChooser.APPROVE_OPTION) {
// si scrive il contenuto della casella di testo nel file
écrireFichier(jFileChooser1.getSelectedFile());
}//if
}
// lireFichier
private void écrireFichier(File fichier){
// scrive il contenuto della casella di testo in un file
// alcuni dati
PrintWriter PRN=null;
try{
// apertura del file in modalità scrittura
PRN=new PrintWriter(new FileWriter(fichier));
// si scrive il contenuto della casella di testo
PRN.print(txtTexte.getText());
// chiude il file
PRN.close();
}catch(Exception ex){
// si è verificato un errore
txtTexte.setText(""+ex);
}//catch
}
Non commenteremo il codice dei metodi btnEffacer_Click, lireFichier e écrireFichier, poiché non apportano nulla di nuovo rispetto a quanto già visto. Ci soffermeremo sulla classe JFileChooser e sul suo utilizzo. Questa classe è complessa, del tipo «complicatissima». Qui utilizziamo solo i seguenti metodi:
addChoosableFilter(FileFilter) | imposta i tipi di file proposti per la selezione |
setAcceptAllFileFilterUsed(boolean) | indica se il tipo «Tutti i file» debba essere proposto o meno alla selezione |
File getSelectedFile() | il file (File) selezionato dall'utente |
int showSaveDialog() | metodo che visualizza la finestra di selezione per il salvataggio. Restituisce un risultato di tipo int. Il valore jFileChooser.APPROVE_OPTION indica che l'utente ha effettuato una scelta valida. In caso contrario, l'utente ha annullato la scelta oppure si è verificato un errore. |
setCurrentDirectory | per impostare la directory iniziale da cui l’utente inizierà a esplorare il file system |
setFileFilter(FileFilter) | per impostare il filtro attivo |
Il metodo showSaveDialog visualizza una finestra di selezione simile alla seguente:

1 | elenco a discesa creato con il metodo addChoosableFilter. Contiene i cosiddetti filtri di selezione rappresentati dalla classe FileFilter. Spetta allo sviluppatore definire questi filtri e aggiungerli all'elenco 1. |
2 | cartella corrente, impostata dal metodo setCurrentDirectory se tale metodo è stato utilizzato; in caso contrario, la directory corrente sarà la cartella "Documenti" in Windows o la home directory in Unix. |
3 | nome del file selezionato o digitato direttamente dall’utente. Sarà disponibile con il metodo getSelectedFile() |
4 | Pulsanti Salva/Annulla. Se viene utilizzato il pulsante Enregistrer, il metodo showSaveDialog restituisce il risultato jFileChooser.APPROVE_OPTION |
Come vengono creati i filtri dei file dell’elenco a discesa 1? I filtri vengono aggiunti all’elenco 1 utilizzando il metodo:
addChoosableFilter(FileFilter) | definisce i tipi di file proposti per la selezione |
della classe JFileChooser. Resta da definire la classe FileFilter. Si tratta in realtà della classe javax.swing.filechooser.FileFilter, che è una classe astratta, c.a.d, una classe che non può essere istanziata ma solo derivata. È definita come segue:
FileFilter() | costruttore |
boolean accept(File) | indica se il file f appartiene al filtro o meno |
String getDescription() | stringa di descrizione del filtro |
Facciamo un esempio. Vogliamo che il menu a tendina 1 offra un filtro per selezionare i file *.txt con la descrizione "File di testo (*.txt)".
- dobbiamo creare una classe derivata dalla classe FileFilter
- utilizzare il metodo boolean accept(File f) per restituire il valore true se il nome del file f termina con .txt
- utilizzare il metodo String getDescription() per restituire la descrizione "File di testo (*.txt)"
Questo filtro potrebbe essere definito nella nostra applicazione nel modo seguente:
javax.swing.filechooser.FileFilter filtreTxt = new javax.swing.filechooser.FileFilter(){
public boolean accept(File f){
// si accetta f?
return f.getName().toLowerCase().endsWith(".txt");
}//accettato
public String getDescription(){
// descrizione del filtro
return "Fichiers Texte (*.txt)";
}//getDescription
};
Questo filtro verrebbe aggiunto all'elenco dei filtri dell'oggetto jFileChooser1 tramite l'istruzione:
Tutto ciò, insieme ad alcune altre inizializzazioni, viene eseguito nel metodo moreInit durante la creazione della finestra (cfr. il programma completo sopra riportato). Il codice del pulsante Sauvegarder è il seguente:
void btnSauvegarder_actionPerformed(ActionEvent e) {
// salva il contenuto della casella di testo in un file
// si imposta il filtro iniziale
jFileChooser1.setFileFilter(filtreTxt);
// viene visualizzata la finestra di selezione per il salvataggio
int returnVal = jFileChooser1.showSaveDialog(this);
// L'utente ha selezionato qualcosa?
if(returnVal == JFileChooser.APPROVE_OPTION) {
// si scrive il contenuto della casella di testo nel file
écrireFichier(jFileChooser1.getSelectedFile());
}//if
}
La sequenza delle operazioni è la seguente:
- si imposta il filtro attivo su *.txt per consentire all'utente di cercare preferibilmente questo tipo di file. È presente anche il filtro "Tutti i file", che è stato aggiunto nella procedura moreInit. Si hanno quindi due filtri.
- Viene visualizzata la finestra di selezione per il salvataggio. A questo punto perdiamo il controllo, poiché l’utente utilizza la finestra di selezione per indicare un file dal sistema di file.
- Quando l'utente esce dalla finestra di selezione, si verifica il valore restituito per stabilire se sia necessario o meno salvare la casella di testo. In caso affermativo, deve essere salvata nel file ottenuto tramite il metodo getSelectedFile.
Il codice relativo al pulsante «Carica» è molto simile a quello del pulsante «Salva».
void btnCharger_actionPerformed(ActionEvent e) {
// scelta di un file tramite un oggetto JFileChooser
// si imposta il filtro iniziale
jFileChooser1.setFileFilter(filtreTxt);
// viene visualizzata la finestra di selezione
int returnVal = jFileChooser1.showOpenDialog(this);
// L'utente ha selezionato qualcosa?
if(returnVal == JFileChooser.APPROVE_OPTION) {
// si inserisce il file nel campo di testo
lireFichier(jFileChooser1.getSelectedFile());
}//if
}//btnCharger_actionPerformed
Ci sono due differenze:
- per visualizzare la finestra di selezione dei file, si utilizza il metodo showOpenDialog anziché il metodo showSaveDialog. La finestra di selezione visualizzata è simile a quella visualizzata dal metodo showSaveDialog.
- se l’utente ha selezionato correttamente un file, si chiama il metodo lireFichier anziché il metodo écrireFichier.
5.4.1.1. Finestre di selezione JColorChooser e JFontChooser
Continuiamo l’esempio precedente aggiungendo due nuovi pulsanti:

N. | tipo | nome | ruolo |
6 | JButton | btnCouleur | per impostare il colore dei caratteri di TextBox |
7 | JButton | btnPolice | per impostare il carattere di TextBox |
Il componente JColorChooser, che consente di visualizzare una finestra di selezione del colore, è presente nell'elenco dei componenti Swing di JBuilder:

Inseriamo questo componente nella finestra di progettazione, ma al di fuori del modulo. Non è visibile nel modulo, ma è comunque presente nell’elenco dei componenti della finestra:

La classe JColorChooser è molto semplice. Visualizziamo la finestra di selezione dei colori con il metodo int showDialog:
static Color | showDialog(Component component, String title, Color initialColor) |
Component component | il componente padre della finestra di selezione, solitamente una finestra JFrame |
String title | il titolo nella barra del titolo della finestra di selezione |
Colore intialColor | colore inizialmente selezionato nella casella di selezione |
Se l'utente sceglie un colore, il metodo restituisce un colore; in caso contrario, restituisce il valore null. Il codice associato al pulsante Couleur è il seguente:
void btnCouleur_actionPerformed(ActionEvent e) {
// scelta di un colore del testo tramite il componente JColorChooser
Color couleur;
if((couleur=jColorChooser1.showDialog(this,"Choix d'une couleur",Color.BLACK))!=null){
// si imposta il colore dei caratteri della casella di testo
txtTexte.setForeground(couleur);
}//if
}
La classe Color è definita in java.awt.Color. In essa sono definite diverse costanti, tra cui Color.BLACK per il colore nero. La finestra di selezione visualizzata è la seguente

Curiosamente, la libreria Swing non offre una classe per selezionare un tipo di carattere. Fortunatamente, ci sono le risorse Java disponibili su Internet. Effettuando una ricerca con la parola chiave «JFontChooser», che sembra un possibile nome per una classe di questo tipo, se ne trovano diverse. L’esempio che seguirà ci darà l’opportunità di configurare JBuilder in modo che utilizzi pacchetti non previsti nella sua configurazione iniziale.
Il pacchetto recuperato si chiama swingextras.jar ed è stato collocato nella cartella <jdk>\jre\lib\perso, dove <jdk> indica la directory di installazione del JDK utilizzato da JBuilder. Avrebbe potuto essere collocato in qualsiasi altra posizione.
![]() | ![]() |
Diamo un’occhiata al contenuto del pacchetto SwingExtras.jar:

Qui si trova il codice sorgente Java dei componenti inclusi nel pacchetto. Sono presenti anche le classi stesse:

Da questo archivio, si noti che la classe JFontChooser si chiama in realtà com.lamatek.swingextras.JFontChooser. Se non si desidera scrivere il nome completo, sarà necessario scrivere all’inizio del programma:
In che modo il compilatore e la macchina virtuale Java riusciranno a individuare questo nuovo pacchetto? Nel caso di un utilizzo diretto di JDK, ciò è già stato spiegato e il lettore potrà trovare le spiegazioni nel paragrafo dedicato ai pacchetti Java. Qui descriviamo in dettaglio il metodo da utilizzare con JBuilder. I pacchetti vengono configurati nel menu Opzioni/Configura JDK:

1 | Il pulsante Modifier (1) consente di indicare a JBuilder quale JDK utilizzare. In questo esempio, JBuilder aveva portato con sé JDK 1.3.1. Quando è stato rilasciato il JDK 1.4, è stato installato separatamente dal JBuilder e si è utilizzato il pulsante Modifier per indicare a JBuilder diutilizzare d'ora in poi la versione JDK 1.4, specificandone la directory di installazione |
2 | directory di base di JDK attualmente utilizzata da JBuilder |
3 | elenco degli archivi Java (.jar) utilizzati da JBuilder. È possibile aggiungerne altri tramite il pulsante Ajouter (4) |
4 | Il pulsante Ajouter (4) consente di aggiungere nuovi pacchetti che JBuilder utilizzerà sia per la compilazione che per l'esecuzione dei programmi. Qui lo abbiamo utilizzato per aggiungere il pacchetto SwingExtras.jar (5) |
Ora JBuilder è configurato correttamente per poter utilizzare la classe JFontChooser. Tuttavia, per utilizzarla correttamente, dovremmo avere accesso alla definizione di questa classe. L'archivio swingextras.jar contiene file HTML che potremmo estrarre per sfruttarli. Ma non è necessario. La documentazione Java inclusa nei file .jar è direttamente accessibile da JBuilder. A tal fine, occorre configurare la scheda Documentation (6) sopra indicata. Si ottiene la seguente nuova finestra:

Il pulsante Ajouter ci permette di specificare che il file SwingExtras.jar deve essere analizzato per la documentazione. Una volta completata questa operazione, si può constatare che si ha effettivamente accesso alla documentazione di SwingExtras.jar. Ciò si traduce in diversi vantaggi:
- se si inizia a scrivere l’istruzione di importazione
si noterà che JBuilder fornisce un aiuto:

Il pacchetto com.lamatek è stato trovato correttamente.
- Se ora si passa al programma seguente:
eseguendo F1 sulla parola chiave JFontChooser, si ottiene una guida su questa classe:

Nella barra di stato 1 si vede che viene effettivamente utilizzato un file HTML del pacchetto swingextras.jar. L'esempio sopra riportato è sufficientemente esplicito per poter scrivere il codice del pulsante Police della nostra applicazione:
void btnPolice_actionPerformed(ActionEvent e) {
// scelta di un carattere di testo tramite il componente JFontChooser
jFontChooser1 = new JFontChooser(new Font("Arial", Font.BOLD, 12));
if (jFontChooser1.showDialog(this, "Choix d'une police") == JFontChooser.ACCEPT_OPTION) {
// si modifica il carattere della casella di testo
txtTexte.setFont(jFontChooser1.getSelectedFont());
}//if
}
La finestra di selezione visualizzata dal metodo showDialog sopra riportato è la seguente:

5.5. L'applicazione grafica IMPOTS
Riprendiamo l’applicazione IMPOTS già trattata due volte. Ora vi aggiungiamo un’interfaccia grafica:

I controlli sono i seguenti
n. | tipo | nome | ruolo |
1 | JRadioButton | rdOui | spuntare se sposato |
2 | JRadioButton | rdNon | da spuntare se non sposato |
3 | JSpinner | spinEnfants | numero di figli del contribuente Minimo=0, Massimo=20, Incremento=1 |
4 | JTextField | txtSalaire | stipendio annuo del contribuente in F |
5 | JLabel | lblImpots | importo dell'imposta da versare |
6 | JTextField | txtStatus | campo dei messaggi di stato - non modificabile |
Il menu è il seguente:
opzione principale | opzione secondaria | nome | ruolo |
Imposte | |||
Inizializza | mnuInitialiser | carica i dati necessari al calcolo da un file di testo | |
Calcola | mnuCalculer | calcola l'imposta da pagare quando tutti i dati necessari sono presenti e corretti | |
Cancella | mnuEffacer | riporta il modulo allo stato iniziale | |
Esci | mnuQuitter | chiude l'applicazione |
Regole di funzionamento
- il menu Calculer rimane disattivato finché il campo dello stipendio è vuoto
- se, all’avvio del calcolo, si riscontra che lo stipendio non è corretto, viene segnalato l’errore:

Il programma è riportato di seguito. Utilizza la classe impots creata nel capitolo dedicato alle classi. Una parte del codice generato automaticamente da JBuilder non è stata qui riprodotta.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.io.*;
import java.util.*;
import javax.swing.event.*;
public class frmImpots extends JFrame {
// i componenti della finestra
JPanel contentPane;
JMenuBar jMenuBar1 = new JMenuBar();
JMenu jMenu1 = new JMenu();
JMenuItem mnuInitialiser = new JMenuItem();
JMenuItem mnuCalculer = new JMenuItem();
JMenuItem mnuEffacer = new JMenuItem();
JMenuItem mnuQuitter = new JMenuItem();
JLabel jLabel1 = new JLabel();
JFileChooser jFileChooser1 = new JFileChooser();
JTextField txtStatus = new JTextField();
JRadioButton rdOui = new JRadioButton();
JRadioButton rdNon = new JRadioButton();
JLabel jLabel2 = new JLabel();
JLabel jLabel3 = new JLabel();
JTextField txtSalaire = new JTextField();
JLabel jLabel4 = new JLabel();
JLabel jLabel5 = new JLabel();
JLabel lblImpots = new JLabel();
JLabel jLabel7 = new JLabel();
ButtonGroup buttonGroup1 = new ButtonGroup();
JSpinner spinEnfants=null;
FileFilter filtreTxt=null;
// gli attributi della classe
double[] limites=null;
double[] coeffr=null;
double[] coeffn=null;
impots objImpots=null;
//Creare il frame
public frmImpots() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
// altre inizializzazioni
moreInit();
}
// inizializzazione del modulo
private void moreInit(){
// menu «Calcola» disabilitato
mnuCalculer.setEnabled(false);
// campi di immissione disabilitati
txtSalaire.setEditable(false);
txtSalaire.setBackground(Color.WHITE);
// campo di stato
txtStatus.setBackground(Color.WHITE);
// selettore "Figli" - da 0 a 20 figli
spinEnfants=new JSpinner(new SpinnerNumberModel(0,0,20,1));
spinEnfants.setBounds(new Rectangle(137,60,40,27));
contentPane.add(spinEnfants);
// filtro *.txt per la casella di selezione
filtreTxt = new javax.swing.filechooser.FileFilter(){
public boolean accept(File f){
// si accetta la "f"?
return f.getName().toLowerCase().endsWith(".txt");
}//accettato
public String getDescription(){
// descrizione del filtro
return "Fichiers Texte (*.txt)";
}//getDescription
};
// si aggiunge il filtro *.txt
jFileChooser1.addChoosableFileFilter(filtreTxt);
// si desidera anche il filtro per tutti i file
jFileChooser1.setAcceptAllFileFilterUsed(true);
// si imposta la directory di partenza della cartella FileChooser
jFileChooser1.setCurrentDirectory(new File("."));
}//moreInit
//Inizializzare il componente
private void jbInit() throws Exception {
................
}
//Sostituito, in modo da poter uscire quando la finestra viene chiusa
protected void processWindowEvent(WindowEvent e) {
.....................
}
void mnuQuitter_actionPerformed(ActionEvent e) {
// si esce dall'applicazione
System.exit(0);
}
void mnuInitialiser_actionPerformed(ActionEvent e) {
// si carica il file dei dati
// che si seleziona con la casella di selezione JFileChooser1
jFileChooser1.setFileFilter(filtreTxt);
if (jFileChooser1.showOpenDialog(this)!=JFileChooser.APPROVE_OPTION)
return;
// si elabora il file selezionato
try{
// lettura dei dati
lireFichier(jFileChooser1.getSelectedFile());
// creazione dell'oggetto «imposte»
objImpots=new impots(limites,coeffr,coeffn);
// conferma
txtStatus.setText("Données chargées");
// lo stipendio può essere modificato
txtSalaire.setEditable(true);
// non sono più possibili modifiche
mnuInitialiser.setEnabled(false);
}catch(Exception ex){
// problema
txtStatus.setText("Erreur : " + ex.getMessage());
// fine
return;
}//catch
}
private void lireFichier(File fichier) throws Exception {
// le tabelle di dati
ArrayList aLimites=new ArrayList();
ArrayList aCoeffR=new ArrayList();
ArrayList aCoeffN=new ArrayList();
String[] champs=null;
// apertura del file in lettura
BufferedReader IN=new BufferedReader(new FileReader(fichier));
// si legge il file riga per riga
// sono della forma limite coeffr coeffn
String ligne=null;
int numLigne=0; // numero della riga corrente
while((ligne=IN.readLine())!=null){
// un'altra riga
numLigne++;
// si scompone la riga in campi
champs=ligne.split("\\s+");
// 3 campi?
if(champs.length!=3)
throw new Exception("ligne " + numLigne + "erronée dans fichier des données");
// si recuperano i tre campi
aLimites.add(champs[0]);
aCoeffR.add(champs[1]);
aCoeffN.add(champs[2]);
}//while
// chiusura del file
IN.close();
// trasferimento dei dati in array delimitati
int n=aLimites.size();
limites=new double[n];
coeffr=new double[n];
coeffn=new double[n];
for(int i=0;i<n;i++){
limites[i]=Double.parseDouble((String)aLimites.get(i));
coeffr[i]=Double.parseDouble((String)aCoeffR.get(i));
coeffn[i]=Double.parseDouble((String)aCoeffN.get(i));
}//for
}
void mnuCalculer_actionPerformed(ActionEvent e) {
// calcolo dell'imposta
// verifica dello stipendio
int salaire=0;
try{
salaire=Integer.parseInt(txtSalaire.getText().trim());
if(salaire<0) throw new Exception();
}catch (Exception ex){
// messaggio di errore
txtStatus.setText("Salaire incorrect. Recommencez");
// focus sul campo errato
txtSalaire.requestFocus();
// ritorno all'interfaccia
return;
}
// numero di figli
Integer InbEnfants=(Integer)spinEnfants.getValue();
// calcolo dell'imposta
lblImpots.setText(""+objImpots.calculer(rdOui.isSelected(),InbEnfants.intValue(),salaire));
// cancellazione messaggio di stato
txtStatus.setText("");
}
void txtSalaire_caretUpdate(CaretEvent e) {
// lo stipendio è cambiato - si aggiorna il menu "Calcola"
mnuCalculer.setEnabled(! txtSalaire.getText().trim().equals(""));
}
void mnuEffacer_actionPerformed(ActionEvent e) {
// azzeramento del modulo
rdNon.setSelected(true);
spinEnfants.getModel().setValue(new Integer(0));
txtSalaire.setText("");
mnuCalculer.setEnabled(false);
lblImpots.setText("");
}
}
Qui abbiamo utilizzato un componente disponibile solo a partire dalla versione 1.4 di JDK, ovvero il JSpinner. Si tratta di un incrementatore, che in questo caso permette all’utente di impostare il numero di figli. Questo componente Swing non era disponibile nella barra dei componenti Swing di JBuilder 6 utilizzata per il test. Ciò non ne impedisce comunque l’utilizzo, anche se la procedura è leggermente più complessa rispetto a quella prevista per i componenti disponibili nella barra dei componenti. Infatti, non è possibile trascinare il componente JSpinner sul modulo durante la fase di progettazione. È necessario farlo in fase di esecuzione. Diamo un’occhiata al codice che lo realizza:
// spinner Figli - inserire un numero compreso tra 0 e 20 figli
spinEnfants=new JSpinner(new SpinnerNumberModel(0,0,20,1));
spinEnfants.setBounds(new Rectangle(137,60,40,27));
contentPane.add(spinEnfants);
La prima riga crea il componente JSpinner. Questo componente può essere utilizzato per diversi scopi e non solo come incrementatore di numeri interi, come in questo caso. L'argomento del costruttore JSpinner è in questo caso un modello di incrementatore di numeri che accetta quattro parametri (valore, min, max, incremento). Il componente ha la seguente forma:
![]()
valeur | valore iniziale visualizzato nel componente |
min | valore minimo visualizzabile nel componente |
max | valore massimo visualizzabile nel componente |
incrément | valore di incremento del valore visualizzato quando si utilizzano le frecce su/giù del componente |
Il valore del componente si ottiene tramite il suo metodo getValue, che restituisce un tipo Object. Da qui derivano alcune conversioni di tipo per ottenere l'intero di cui abbiamo bisogno:
// numero di figli
Integer InbEnfants=(Integer)spinEnfants.getValue();
// calcolo dell'imposta
lblImpots.setText(""+objImpots.calculer(rdOui.isSelected(),
InbEnfants.intValue(),salaire));
Una volta definito il componente JSpinner, questo viene inserito nella finestra:
Prima di tutto, l'utente deve utilizzare l'opzione di menu Initialiser che crea un oggetto impots con il costruttore
della classe impots. Si ricorda che quest’ultima è stata definita a titolo di esempio nel capitolo dedicato alle classi. Si rimanda a tale capitolo se necessario. I tre array necessari al costruttore vengono popolati a partire dal contenuto di un file di testo con il seguente formato:
12620.0 | 0 | 0 |
13190 | 0,05 | 631 |
15640 | 0,1 | 1290,5 |
24.740 | 0,15 | 2072,5 |
31810 | 0,2 | 3309,5 |
39.970 | 0,25 | 4900 |
48360 | 0,3 | 6898,5 |
55790 | 0,35 | 9316,5 |
92970 | 0,4 | 12106 |
127.860 | 0,45 | 16754,5 |
151250 | 0,50 | 23147,5 |
172.040 | 0,55 | 30710 |
195.000 | 0,60 | 39312 |
0 | 0,65 | 49062 |
Ogni riga contiene tre numeri separati da almeno uno spazio. Questo file di testo viene selezionato dall'utente tramite un componente JFileChooser. Una volta creato l'oggetto di tipo impots, non resta che lasciare che l'utente fornisca le tre informazioni necessarie: stato civile (coniugato o no), numero di figli, stipendio annuo, e chiamare il metodo calculer della classe impots. L'operazione può essere ripetuta più volte. L'oggetto di tipo impots viene invece creato una sola volta, quando si utilizza l'opzione Initialiser.
5.6. Scrittura di applet
5.6.1. Introduzione
Una volta sviluppata un'applicazione con interfaccia grafica, è piuttosto semplice trasformarla in applet. Una volta salvata su un computer A, può essere scaricata tramite un browser web da un computer B collegato a Internet. L'applicazione iniziale viene così condivisa tra numerosi utenti e questo è il principale vantaggio della conversione di un'applicazione in applet. Tuttavia, non tutte le applicazioni possono essere convertite in questo modo: per non arrecare disturbo all'utente che utilizza un'applet nel proprio browser, l'ambiente dell'applet è regolamentato:
- un’applet non può leggere né scrivere sul disco dell’utente
- può comunicare solo con il computer da cui è stata scaricata dal browser.
Si tratta di restrizioni significative. Esse implicano, ad esempio, che un’applicazione che necessiti di leggere informazioni da un file o da un database dovrà richiederle tramite un’applicazione intermediaria situata sul server da cui è stata scaricata.
La struttura generale di una semplice applicazione web è la seguente:

- il client richiede un documento HTML al server Web, solitamente tramite un browser. Questo documento può contenere un’applet che funzionerà come un’applicazione grafica autonoma all’interno del documento HTML visualizzato dal browser del client.
- Tale applet potrà accedere ai dati, ma solo a quelli presenti sul server web. Non avrà accesso né alle risorse del computer client su cui viene eseguita, né a quelle di altri computer della rete diversi da quello da cui è stata scaricata.
5.6.2. La classe JApplet
5.6.2.1. Définition
Un'applicazione può essere scaricata da un browser Web se è un'istanza della classe java.applet.Applet o della classe javax.swing.JApplet. Quest’ultima deriva dalla prima, che a sua volta deriva dalla classe Panel, derivata a sua volta dalla classe Container. Un'istanza di tipo Applet o JApplet, essendo di tipo container, potrà quindi contenere componenti (Component) quali pulsanti, caselle di controllo, elenchi, ecc. Forniamo alcune indicazioni sul ruolo dei diversi metodi:
Metodo | Funzione |
public void destroy(); | distrugge l’istanza dell’applet |
public AppletContext getAppletContext(); | recupera il contesto di esecuzione dell'applet (documento HTML in cui si trova, altre applet dello stesso documento, …) |
public String getAppletInfo(); | restituisce una stringa di caratteri contenente informazioni sull'applet |
public AudioClip getAudioClip(URL url); | carica il file audio specificato da URL |
public AudioClip getAudioClip(URL url, String name); | carica il file audio specificato da URL/name |
public URL getCodeBase(); | restituisce l'URL dell'applet |
public URL getDocumentBase(); | restituisce il URL del documento HTML contenente l'applet |
public Image getImage(URL url); | recupera l'immagine specificata da URL |
public Image getImage(URL url, String name); | recupera l'immagine specificata da URL/name |
public String getParameter(String name); | recupera il valore del parametro name contenuto nel tag <applet> del documento HTML che contiene l'applet. |
public void init(); | questo metodo viene eseguito dal browser al primo avvio dell'applet |
public boolean isActive(); | Stato dell'applet |
public void play(URL url); | riproduce il file audio specificato da URL |
public void play(URL url, String name); | riproduce il file audio specificato da UR/name |
public void resize(Dimension d); | imposta le dimensioni del riquadro dell'applet |
public void resize(int width, int height); | idem |
public final void setStub(AppletStub stub); | |
public void showStatus(String msg); | inserisce un messaggio nella barra di stato dell'applet |
public void start(); | questo metodo viene eseguito dal browser ogni volta che viene visualizzato il documento contenente l'applet |
public void stop(); | questo metodo viene eseguito dal browser ogni volta che il documento contenente l'applet viene chiuso per passare a un altro (cambio di URL da parte dell'utente) |
La classe JApplet ha apportato alcuni miglioramenti alla classe Applet, in particolare la capacità di contenere componenti JMenuBar e c.a.d. nei menu, cosa che non era possibile con la classe Applet.
5.6.2.2. Esecuzione di un'applet: i metodi init, start e stop
Quando un browser carica un’applet, ne chiama tre metodi:
init | Questo metodo viene chiamato durante il caricamento iniziale dell’applet. Qui andranno inserite le inizializzazioni necessarie all’applicazione. |
start | Questo metodo viene chiamato ogni volta che il documento contenente l'applet diventa il documento attivo del browser. Pertanto, quando un utente carica un'applet, i metodi init e start verranno eseguiti in questo ordine. Quando l'utente uscirà dal documento per visualizzarne un altro, verrà eseguito il metodo stop. Quando tornerà su quel documento in un secondo momento, verrà eseguito il metodo start. |
stop | Questo metodo viene chiamato ogni volta che l'utente esce dal documento contenente l'applet. |
Per molte applet è necessario solo il metodo init. I metodi start e stop sono necessari solo se l'applicazione avvia attività (thread) che girano in parallelo e in modo continuo, spesso all'insaputa dell'utente. Quando l'utente esce dal documento, la parte visibile dell'applicazione scompare, ma queste attività in background continuano a funzionare. Spesso ciò è superfluo. Si approfitta quindi della chiamata del browser al metodo **stop per arrestarli. Se l’utente torna al documento, si approfitta della chiamata del browser al metodo **start per riavviarli.
Prendiamo ad esempio un’applet che presenta un orologio nella propria interfaccia grafica. Questo viene gestito da un’attività in background (thread). Quando l’utente esce dalla pagina dell’applet nel browser, è superfluo mantenere l’orologio che è diventato invisibile: nel metodo stop dell’applet, si interromperà il thread che gestisce l’orologio. Nel metodo start, lo si riavvierà in modo che, quando l’utente torna alla pagina dell’applet, ritrovi un orologio aggiornato.
5.6.3. Trasformazione di un'applicazione grafica in un'applet
Si suppone qui che tale trasformazione sia possibile, ovvero che rispetti le restrizioni di esecuzione delle applet. Un’applicazione viene avviata tramite il metodo main di una delle sue classi:
Un'applicazione di questo tipo viene trasformata in un'applet nel modo seguente:
import java.applet.JApplet;
…
public class application extends JApplet{
…
public void init(){
…
}
…
}// fine classe
Si notino i seguenti punti:
- la classe application deriva ora dalla classe JApplet
- il metodo main è sostituito dal metodo init.
A titolo di esempio, torniamo su un'applicazione già esaminata: la gestione delle liste.

I componenti di questa finestra sono i seguenti:
n. | tipo | nome | funzione |
1 | JTextField | txtSaisie | campo di immissione |
2 | JList | jList1 | elenco contenuto in un contenitore jScrollPane1 |
3 | JList | jList2 | elenco contenuto in un contenitore jScrollPane2 |
4 | JButton | cmd1To2 | trasferisce gli elementi selezionati dall'elenco 1 all'elenco 2 |
5 | JButton | cmd2To1 | esegue l'operazione inversa |
6 | JButton | cmdRaz1 | svuota l'elenco 1 |
7 | JButton | cmdRaz2 | svuota l'elenco 2 |
La struttura dell'applicazione era la seguente:
public class interfaceAppli extends JFrame {
JPanel contentPane;
JLabel jLabel1 = new JLabel();
JLabel jLabel2 = new JLabel();
JLabel jLabel3 = new JLabel();
JTextField txtSaisie = new JTextField();
JButton cmd1To2 = new JButton();
JButton cmd2To1 = new JButton();
DefaultListModel v1=new DefaultListModel();
DefaultListModel v2=new DefaultListModel();
JList jList1 = new JList(v1);
JList jList2 = new JList(v2);
JScrollPane jScrollPane1 = new JScrollPane();
JScrollPane jScrollPane2 = new JScrollPane();
JButton cmdRaz1 = new JButton();
JButton cmdRaz2 = new JButton();
JLabel jLabel4 = new JLabel();
/**Creare la tabella*/
public interfaceAppli() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}//interfaceAppli
/**Inizializzare il componente*/
private void jbInit() throws Exception {
...
txtSaisie.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
txtSaisie_actionPerformed(e);
}
});
...
// Jlist1 viene inserito nel contenitore jScrollPane1
jScrollPane1.getViewport().add(jList1, null);
// Jlist2 viene inserito nel contenitore jScrollPane2
jScrollPane2.getViewport().add(jList2, null);
...
}
/**Sostituito, in modo da poter uscire quando la finestra viene chiusa*/
protected void processWindowEvent(WindowEvent e) {
...
}
void txtSaisie_actionPerformed(ActionEvent e) {
.............
}//classe
void cmdRaz1_actionPerformed(ActionEvent e) {
// svuota lista 1
v1.removeAllElements();
}//comando Raz1
void cmdRaz2_actionPerformed(ActionEvent e) {
// svuota lista 2
v2.removeAllElements();
}///cmd Raz2
Per trasformare la classe appli in applet, occorre procedere come segue:
- modificare la classe precedente interfaceAppli in modo che non derivi più da JFrame ma da JApplet:
- eliminare l'istruzione che definisce il titolo della finestra JFrame. Un'applet JApplet non ha una barra del titolo
- modificare il costruttore in metodo init e in questo metodo eliminare la gestione degli eventi della finestra (WindowListener, ...). Un'applet è un contenitore che non può essere ridimensionato né chiuso.
/**Costruire il quadro*/
public init() {
// enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}//interfaceAppli
- Il metodo processWindowEvent deve essere eliminato o messo in commento
/**Sostituito, in modo da poter uscire quando la finestra è chiusa*/
//protected void processWindowEvent(WindowEvent e) {
// super.processWindowEvent(e);
// if (e.getID() == WindowEvent.WINDOW_CLOSING) {
// System.exit(0);
// }
// }
A titolo di esempio, riportiamo il codice completo dell'applet, ad eccezione della parte generata automaticamente da JBuilder
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class interfaceAppli extends JApplet {
JPanel contentPane;
JLabel jLabel1 = new JLabel();
JLabel jLabel2 = new JLabel();
JLabel jLabel3 = new JLabel();
JTextField txtSaisie = new JTextField();
JButton cmd1To2 = new JButton();
JButton cmd2To1 = new JButton();
DefaultListModel v1=new DefaultListModel();
DefaultListModel v2=new DefaultListModel();
JList jList1 = new JList(v1);
JList jList2 = new JList(v2);
JScrollPane jScrollPane1 = new JScrollPane();
JScrollPane jScrollPane2 = new JScrollPane();
JButton cmdRaz1 = new JButton();
JButton cmdRaz2 = new JButton();
JLabel jLabel4 = new JLabel();
/**Costruire la cornice*/
public void init() {
// enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}//interfaceAppli
/**Inizializza il componente*/
private void jbInit() throws Exception {
//setIconImage(Toolkit.getDefaultToolkit().createImage(interfaceAppli.class.getResource("[Votre icône]")));
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(null);
this.setSize(new Dimension(400, 308));
// this.setTitle("JList");
jScrollPane1.setBounds(new Rectangle(37, 133, 124, 101));
jScrollPane2.setBounds(new Rectangle(232, 132, 124, 101));
.............
}
void txtSaisie_actionPerformed(ActionEvent e) {
// il testo inserito è stato convalidato
// viene recuperato senza gli spazi iniziali e finali
String texte=txtSaisie.getText().trim();
// se è vuoto, non lo si accetta
if(texte.equals("")){
// messaggio di errore
JOptionPane.showMessageDialog(this,"Vous devez taper un texte",
"Erreur",JOptionPane.WARNING_MESSAGE);
// fine
return;
}//if
// se non è vuoto, lo si aggiunge ai valori dell'elenco 1
v1.addElement(texte);
// e si svuota il campo di immissione
txtSaisie.setText("");
}
void cmd1To2_actionPerformed(ActionEvent e) {
// trasferimento degli elementi selezionati dall'elenco 1 all'elenco 2
transfert(jList1,jList2);
}//cmd1To2
private void transfert(JList L1, JList L2){
// trasferimento degli elementi selezionati dall'elenco 1 all'elenco 2
// si recupera la tabella degli indici degli elementi selezionati in L1
int[] indices=L1.getSelectedIndices();
// c'è qualcosa da fare?
if (indices.length==0) return;
// si recuperano i valori da L1
DefaultListModel v1=(DefaultListModel)L1.getModel();
// e quelli di L2
DefaultListModel v2=(DefaultListModel)L2.getModel();
for(int i=indices.length-1;i>=0;i--){
// si aggiungono a L2 i valori selezionati in L1
v2.addElement(v1.elementAt(indices[i]));
// gli elementi di L1 copiati in L2 devono essere eliminati da L1
v1.removeElementAt(indices[i]);
}//per
}//trasferimento
private void affiche(String message){
// visualizza messaggio
JOptionPane.showMessageDialog(this,message,
"Suivi",JOptionPane.INFORMATION_MESSAGE);
}// visualizza
void cmd2To1_actionPerformed(ActionEvent e) {
// trasferimento degli elementi selezionati da jList2 a jList1
transfert(jList2,jList1);
}//cmd2TO1
void cmdRaz1_actionPerformed(ActionEvent e) {
// svuota elenco 1
v1.removeAllElements();
}//comando Raz1
void cmdRaz2_actionPerformed(ActionEvent e) {
// svuota elenco 2
v2.removeAllElements();
}//comando Raz2
}//classe
È possibile compilare il codice sorgente di questa applet. Lo facciamo qui con il JDK, senza il JBuilder.
E:\data\serge\Jbuilder\interfaces\JApplets\1>javac.bat interfaceAppli.java
E:\data\serge\Jbuilder\interfaces\JApplets\1>dir
12/06/2002 16:40 6 148 interfaceAppli.java
12/06/2002 16:41 527 interfaceAppli$1.class
12/06/2002 16:41 525 interfaceAppli$2.class
12/06/2002 16:41 525 interfaceAppli$3.class
12/06/2002 16:41 525 interfaceAppli$4.class
12/06/2002 16:41 525 interfaceAppli$5.class
12/06/2002 16:41 4 759 interfaceAppli.class
L'applicazione può essere testata con il programma AppletViewer di JDK, che consente di eseguire applet o un browser. A tal fine, è necessario creare il documento HTML appli.htm che conterrà al suo interno l'applet:
<html>
<head>
<title>listes swing</title>
</head>
<body>
<applet
code="interfaceAppli.class"
width="400"
height="300">
</applet>
</body>
</html>
Si tratta di un documento HTML classico, se non fosse per la presenza del tag applet. Quest'ultimo è stato utilizzato con tre parametri:
code="interfaceAppli.class" | nome della classe JAVA compilata da caricare per eseguire l'applet |
width="400" | larghezza del riquadro dell’applet nel documento |
height="300" | altezza del riquadro dell'applet nel documento |
Una volta creato il file appli.htm, è possibile caricarlo con il programma appletviewer contenuto in JDK oppure con un browser. Digitare in una finestra DOS il seguente comando nella cartella del file appli.htm:
appletviewer appli.htm
Si suppone che la directory dell’eseguibile appletviewer.exe si trovi nella directory PATH della finestra DOS; in caso contrario, occorrerebbe specificare il percorso completo dell’eseguibile appletviewer.exe. Si ottiene la seguente finestra:

Si interrompe l’esecuzione dell’applet con l’opzione Applet/Quitter. Proviamo ora l’applet con un browser. Quest’ultimo deve utilizzare una macchina virtuale Java 2 per poter visualizzare i componenti Swing. Fino a poco tempo fa (2001), questo requisito rappresentava un problema poiché Sun produceva JDK che gli editori di browser adottavano solo con notevole ritardo. Alla fine Sun ha risolto questo ostacolo mettendo a disposizione degli utenti un’applicazione chiamata «Java plugin» che consente ai browser Internet Explorer e Netscape Navigator di utilizzare le versioni più recenti di JRE prodotte da Sun (JRE = Java Runtime Environment). I test che seguono sono stati effettuati con IE 5.5 dotato del plugin Java 1.4.
Un primo modo per testare l’applet interfaceAppli.class consiste nel caricare il file HTML appli.htm direttamente nel browser facendo doppio clic su di esso. Il browser visualizzerà quindi la pagina HTML e la relativa applet senza l’ausilio di un server Web:

Come si evince da URL (1), il file è stato caricato direttamente nel browser. Nell’esempio seguente, il file appli.htm è stato richiesto a un server Web Apache in esecuzione sulla porta 81 del computer locale:

5.6.4. L'opzione di formattazione <applet> in un documento HTML
Abbiamo visto che all'interno di un documento HTML, l'applet era indicata dal comando di formattazione (tag) <applet>. Questo comando può avere diversi parametri:
<applet
code=
width=
height=
codebase=
align=
hspace=
vspace=
alt=
>
<param name1=nom1 value=val1>
<param name2=nom2 value=val2>
texte
>
</applet>
Il significato dei parametri è il seguente:
Parametro | Significato |
code | obbligatorio - nome del file .class da eseguire |
width | obbligatorio - larghezza dell'applet nel documento |
height | obbligatorio - altezza … |
codebase | facoltativo - URL della directory contenente l'applet da eseguire. Se codebase non è specificato, l'applet verrà cercata nella directory del documento HTML che la richiama |
align | facoltativo - posizionamento (LEFT, RiGHT, CENTER) dell'applet nel documento |
hspace | facoltativo - margine orizzontale che circonda l'applet espresso in pixel |
vspace | facoltativo - margine verticale che circonda l'applet, espresso in pixel |
alt | facoltativo - testo visualizzato al posto dell'applet se il browser non è in grado di caricarla |
param | facoltativo - parametro passato all'applet che specifica il suo nome (name) e il suo valore (value). L'applet potrà recuperare il valore del parametro nome1 tramite val1=getParameter("nome1") È possibile utilizzare tutti i parametri che si desidera |
texte | facoltativo - verrà visualizzato da qualsiasi browser incapace di eseguire un'applet, ad esempio perché privo di una macchina virtuale Java. |
Prendiamo un esempio per illustrare il passaggio dei parametri a un'applet:
<html>
<head>
<title>paramètres applet</title>
</head>
<body>
<applet code="interfaceParams.class" width="400" height="300">
<param name="param1" value="val1">
<param name="param2" value="val2">
</applet>
</body>
</html>
Il codice Java dell'applet interfaceParams è stato generato come indicato in precedenza. È stata creata un'applicazione JBuilder, quindi sono state apportate le poche modifiche menzionate sopra:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class interfaceParams extends JApplet {
JPanel contentPane;
JScrollPane jScrollPane1 = new JScrollPane();
JLabel jLabel1 = new JLabel();
DefaultListModel params=new DefaultListModel();
JList lstParams = new JList(params);
//Costruire il quadro
public void init() {
// enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
// altre inizializzazioni
moreInit();
}
// inizializzazioni
public void moreInit(){
// visualizza i valori dei parametri dell'applet
params.addElement("nom=param1 valeur="+getParameter("param1"));
params.addElement("nom=param2 valeur="+getParameter("param2"));
}//ulteriori inizializzazioni
//Inizializza il componente
private void jbInit() throws Exception {
............
this.setSize(new Dimension(205, 156));
//this.setTitle("Parametri di un'applet");
jScrollPane1.setBounds(new Rectangle(19, 53, 160, 73));
............
}
}
Esecuzione con AppletViewer:

5.6.5. Accedere a risorse remote da un'applet
Molte applicazioni devono utilizzare informazioni presenti in file o database. Abbiamo già indicato che un'applet non ha accesso alle risorse del computer su cui viene eseguita. Si tratta di una misura di buon senso. Altrimenti basterebbe scrivere un'applet per "spiare" il disco di chi la carica. L'applet ha tuttavia accesso alle risorse del server da cui è stata scaricata, ad esempio ai file. È proprio questo che vedremo ora.
5.6.5.1. La classe URL
Qualsiasi applicazione Java può leggere un file presente su una macchina della rete grazie alla classe java.net.URL (URL = Uniform Resource Locator). Un URL identifica una risorsa di rete, il computer su cui si trova, nonché il protocollo e la porta di comunicazione da utilizzare per recuperarla nella forma:
protocollo:porta//macchina/file
Pertanto, l'URL http://www.ibm.com/index.html indica il file index.html presente sul computer www.ibm.com. È accessibile tramite il protocollo http. La porta non è specificata: il browser utilizzerà la porta 80, che è la porta predefinita del servizio http.
Vediamo in dettaglio alcuni degli elementi della classe URL:
public URL(String spec) | crea un'istanza di URL a partire da una stringa del tipo "protocollo:porta//macchina/file" - genera un'eccezione se la sintassi della stringa non corrisponde a una URL |
public String getFile() | consente di ottenere il campo «file» della stringa «protocollo:porta//macchina/file» dell’oggetto URL |
public String getHost() | consente di ottenere il campo "macchina" dalla stringa "protocollo:porta//macchina/file" dell'URL |
public String getPort() | consente di ottenere il campo porta della stringa "protocollo:porta//macchina/file" da URL |
public String getProtocol() | consente di ottenere il campo "protocollo" dalla stringa "protocollo:porta//macchina/file" di URL |
public URLConnection openConnection() | apre la connessione con la macchina remota getHost() sulla sua porta getPort() secondo il protocollo getProtocol() al fine di leggere il file getFile(). Genera un'eccezione se non è stato possibile aprire la connessione |
public final InputStream openStream() | abbreviazione di openConnection().getInputStream(). Consente di ottenere un flusso di input dal quale sarà possibile leggere il contenuto del file getFile(). Genera un'eccezione se non è stato possibile ottenere il flusso |
public String toString() | visualizza l'identità dell'istanza di URL |
Ci sono due metodi che ci interessano:
- public URL(String spec) per specificare il file da elaborare
- public final InputStream openStream() per elaborarlo
5.6.5.2. Un esempio da console
Scriveremo un programma Java, senza interfaccia grafica, incaricato di visualizzare sullo schermo il contenuto di un URL che gli viene passato come parametro. Un esempio di chiamata potrebbe essere il seguente:
Il programma è relativamente semplice:
import java.net.*; // per la classe URL
import java.io.*; // per i flussi (stream)
public class urlcontenu{
// visualizza il contenuto di URL passato come argomento
// questo contenuto deve essere testo per poter essere leggibile
public static void main (String arg[]){
// verifica degli argomenti
if(arg.length==0){
System.err.println("Syntaxe pg url");
System.exit(0);
}
try{
// creazione di URL
URL url=new URL(arg[0]);
// lettura del contenuto
try{
// creazione del flusso di input
BufferedReader is=new BufferedReader(new InputStreamReader(url.openStream()));
try{
// lettura delle righe di testo nel flusso di input
String ligne;
while((ligne=is.readLine())!=null)
System.out.println(ligne);
} catch (Exception e){
System.err.println("Erreur lecture : " +e);
}
finally{
try { is.close(); } catch (Exception e) {}
}
} catch (Exception e){
System.err.println("Erreur openStream : " +e);
}
} catch (Exception e){
System.err.println("Erreur création URL : " +e);
}
}// fine main
}// fine classe
Dopo aver verificato che fosse presente un argomento, si tenta di creare un URL con esso:
// creazione di URL
URL url=new URL(arg[0]);
La creazione potrebbe non andare a buon fine se l’argomento non rispetta la sintassi dei URL protocole:port//machine/fichier. Se si dispone di un URL sintatticamente corretto, si tenta di creare un flusso di input dal quale sarà possibile leggere righe di testo. Il flusso di input fornito da una funzione URL URL.openStream() fornisce un flusso di tipo InputStream, ovvero un flusso orientato ai caratteri: la lettura avviene carattere per carattere ed è necessario formare le righe manualmente. Per poter leggere le righe di testo, è necessario utilizzare il metodo readLine delle classi BufferedReader o DataInputStream.On; in questo caso è stata scelta BufferedReader. Non resta che trasformare il flusso InputStream di URL in un flusso BufferedReader. Ciò avviene creando un flusso intermedio InputStreamReader:
BufferedReader is=new BufferedReader(new InputStreamReader(url.openStream()));
La creazione di questo flusso potrebbe non andare a buon fine. Si gestisce l’eccezione corrispondente. Una volta ottenuto il flusso, non resta che leggerne le righe di testo e visualizzarle sullo schermo.
String ligne;
while((ligne=is.readLine())!=null)
System.out.println(ligne);
Anche in questo caso la lettura può generare un'eccezione che deve essere gestita. Ecco un esempio di esecuzione del programma che richiede una URL locale:
E:\data\serge\Jbuilder\interfaces\JApplets\3>java urlcontenu http://localhost
<html>
<head>
<title>Bienvenue dans le Serveur Web personnel</title>
</head>
<body bgcolor="#FFFFFF" link="#0080FF" vlink="#0080FF"
topmargin="0" leftmargin="0">
<table border="0" cellpadding="0" cellspacing="0" width="100%"
bgcolor="#000000">
............
</table>
</center></div></td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
5.6.5.3. Un esempio grafico
L'interfaccia grafica sarà la seguente:

Numero | Nome | Tipo | Ruolo |
1 | txtURL | JTextField | URL da leggere |
2 | btnCharger | JButton | pulsante per avviare la riproduzione di URL |
3 | JScrollPane1 | JScrollPane | pannello scorrevole |
4 | lstURL | JList | elenco che mostra il contenuto dell'URL richiesto |
All'esecuzione, otteniamo un risultato analogo a quello del programma da console:

Il codice rilevante dell'applicazione è il seguente:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.net.*;
import java.io.*;
public class interfaceURL extends JFrame {
JPanel contentPane;
JLabel jLabel1 = new JLabel();
JTextField txtURL = new JTextField();
JButton btnCharger = new JButton();
JScrollPane jScrollPane1 = new JScrollPane();
DefaultListModel lignes=new DefaultListModel();
JList lstURL = new JList(lignes);
//Costruire il frame
public interfaceURL() {
..............
}
//Inizializzazione del componente
private void jbInit() throws Exception {
..............
}
//Sostituito, così possiamo uscire quando la finestra viene chiusa
protected void processWindowEvent(WindowEvent e) {
...................
}
void txtURL_caretUpdate(CaretEvent e) {
// imposta lo stato del pulsante Carica
btnCharger.setEnabled(! txtURL.getText().trim().equals(""));
}
void btnCharger_actionPerformed(ActionEvent e) {
// visualizza il contenuto di URL nell'elenco
try{
afficherURL(txtURL.getText().trim());
}catch(Exception ex){
// visualizza l'errore
JOptionPane.showMessageDialog(this,"Erreur : " + ex.getMessage(),"Erreur",JOptionPane.ERROR_MESSAGE);
}//try-catch
}
private void afficherURL(String strURL) throws Exception {
// visualizza il contenuto di URL strURL nell'elenco
// nessuna eccezione viene gestita in modo specifico. Ci si limita a segnalarle
// creazione di URL
URL url=new URL(strURL);
// creazione del flusso di input
BufferedReader IN=new BufferedReader(new InputStreamReader(url.openStream()));
// lettura delle righe di testo nel flusso di input
String ligne;
while((ligne=IN.readLine())!=null)
lignes.addElement(ligne);
// chiusura del flusso di lettura
IN.close();
}
}
5.6.5.4. Un'applet
L'applicazione grafica precedente viene trasformata in un'applet, come già illustrato più volte. L'applet viene inserita in un documento HTML appliURL.htm:
<html>
<head>
<title>Applet lisant une URL</title>
</head>
<body>
<h1>Applet lisant une URL</h1>
<applet
code="appletURL.class"
width="400"
height="300"
>
</applet>
</body>
</html>

Nell'esempio sopra riportato, il browser ha richiesto l'http://localhost:81/Japplets/2/appliURL.htm URL a un server web apache in esecuzione sulla porta 81. L'applet è stata quindi visualizzata nel browser. All’interno di essa, è stato richiesto nuovamente l’URL http://localhost:81/Japplets/2/appliURL.htm per verificare che venisse effettivamente recuperato il file appliURL.htm che avevamo creato. Ora proviamo a caricare un file URL che non appartiene al computer che ha generato l’applet (in questo caso localhost):

Il caricamento del file URL è stato rifiutato. Qui si riscontra il vincolo legato alle applet: esse possono accedere solo alle risorse di rete del computer da cui sono state scaricate. Esiste un modo per l’applet di aggirare questa limitazione, ovvero delegare le richieste di rete a un programma server situato sul computer da cui è stata scaricata. Questo programma effettuerà le richieste di rete al posto dell’applet e le restituirà i risultati. Si tratta di un programma relay.
5.7. L’applet IMPOTS
Ora trasformeremo l’applicazione grafica IMPOTS in un’applet. Ciò presenta un certo interesse: l’applicazione diventerà disponibile per qualsiasi utente di Internet dotato di un browser e di un plugin Java 1.4 (grazie al componente JSpinner). La nostra applicazione diventa così globale... Questa modifica richiederà qualcosa di più della semplice trasformazione da applicazione grafica ad applet, ormai diventata un classico. L’applicazione utilizza un’opzione di menu Initialiser il cui scopo è leggere il contenuto di un file locale. Tuttavia, se immaginiamo un’applicazione web, ci rendiamo conto che questo schema non è più valido:

È evidente che i dati che definiscono le aliquote fiscali si troveranno sul server web e non su ciascuna delle macchine client. Il file da leggere sul server web sarà collocato nella stessa cartella dell’applet e l’opzione Initialiser dovrà recuperarlo da lì. Gli esempi precedenti hanno mostrato come farlo. Inoltre, per selezionare il file dei dati localmente, era stato utilizzato un componente JFileChooser che qui non è più necessario.
Il documento HTML contenente l’applet sarà il seguente:
<html>
<head>
<title>Applet de calcul d'impôts</title>
</head>
<body>
<h2>Calcul d'impôts</h2>
<applet
code="appletImpots.class"
width="320"
height="270"
>
<param name="data" value="impots.txt">
Si noti il parametro data, il cui valore è il nome del file contenente i dati della tabella delle aliquote fiscali. Il documento HTML, la classe appletImpots, la classe impots e il file impots.txt si trovano tutti nella stessa cartella del server Web:
E:\data\serge\web\JApplets\impots>dir
12/06/2002 13:24 247 impots.txt
13/06/2002 10:17 654 appletImpots$2.class
13/06/2002 10:17 653 appletImpots$3.class
13/06/2002 10:17 653 appletImpots$4.class
13/06/2002 10:17 651 appletImpots$5.class
13/06/2002 10:06 651 appletImpots$6.class
13/06/2002 10:17 8 655 appletImpots.class
13/06/2002 10:17 657 appletImpots$1.class
13/06/2002 10:24 286 appletImpots.htm
13/06/2002 10:17 1 305 impots.class
Il codice dell'applet è il seguente (abbiamo evidenziato solo le modifiche rispetto all'applicazione grafica):
...........
import java.net.*;
import java.applet.Applet;
public class appletImpots extends JApplet {
// i componenti della finestra
JPanel contentPane;
............................
// gli attributi della classe
double[] limites=null;
double[] coeffr=null;
double[] coeffn=null;
impots objImpots=null;
String urlDATA=null;
//Creazione del frame
public void init() {
//enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
// altre inizializzazioni
moreInit();
}
// inizializzazione del modulo
private void moreInit(){
// menu «Calcola» disabilitato
mnuCalculer.setEnabled(false);
................
// si recupera il nome del file della tabella delle imposte
String nomFichier=getParameter("data");
// errore?
if(nomFichier==null){
// messaggio di errore
txtStatus.setText("Le paramètre data de l'applet n'a pas été initialisé");
// si blocca l'opzione Inizializza
mnuInitialiser.setEnabled(false);
// fine
return;
}//if
// si imposta il URL dei dati
urlDATA=getCodeBase()+"/"+nomFichier;
}//moreInit
//Inizializza il componente
private void jbInit() throws Exception {
...................
}
void mnuQuitter_actionPerformed(ActionEvent e) {
// si esce dall'applicazione
System.exit(0);
}
void mnuInitialiser_actionPerformed(ActionEvent e) {
// caricamento del file di dati
try{
// lettura dei dati
lireDATA();
// creazione dell'oggetto «imposte»
objImpots=new impots(limites,coeffr,coeffn);
................
}
private void lireDATA() throws Exception {
// tabelle di dati
ArrayList aLimites=new ArrayList();
ArrayList aCoeffR=new ArrayList();
ArrayList aCoeffN=new ArrayList();
String[] champs=null;
// apertura del file in modalità di lettura
BufferedReader IN=new BufferedReader(new InputStreamReader(new URL(urlDATA).openStream()));
// si legge il file riga per riga
....................
}
void mnuCalculer_actionPerformed(ActionEvent e) {
// calcolo dell'imposta
......................
}
void txtSalaire_caretUpdate(CaretEvent e) {
..........
}
void mnuEffacer_actionPerformed(ActionEvent e) {
...............
}
}
Qui ci limitiamo a commentare le modifiche derivanti dal fatto che il file di dati da leggere si trova ora su una macchina remota anziché su una macchina locale:
Il nome del file di dati da leggere, URL, viene ricavato dal seguente codice:
// recupero del nome del file della tabella delle imposte
String nomFichier=getParameter("data");
// errore?
if(nomFichier==null){
// messaggio di errore
txtStatus.setText("Le paramètre data de l'applet n'a pas été initialisé");
// si blocca l'opzione Inizializza
mnuInitialiser.setEnabled(false);
// fine
return;
}//if
// si imposta il URL dei dati
urlDATA=getCodeBase()+"/"+nomFichier;
Ricordiamo che il nome del file "impots.txt" è stato passato nel parametro data dell'applet:
Il codice sopra riportato inizia quindi recuperando il valore del parametro data, gestendo un eventuale errore. Se il valore di URL del documento HTML contenente l’applet è http://localhost:81/JApplets/impots/appletImpots.htm, il URL del file impots.txt sarà http://localhost:81/JApplets/impots/impots.txt. Dobbiamo costruire il nome di questo URL. Il metodo getCodeBase() dell'applet fornisce il URL della cartella da cui è stato recuperato il documento HTML contenente l'applet, quindi, nel nostro esempio, http://localhost:81/JApplets/impots. L’istruzione seguente consente quindi di costruire l’URL del file di dati:
Nel metodo lireFichier(), che legge il contenuto di URL e urlData, si trova la creazione del flusso di input che consentirà di leggere i dati:
// apertura del file in lettura
BufferedReader IN=new BufferedReader(new InputStreamReader(new URL(urlDATA).openStream()));
A questo punto, non è più possibile distinguere se i dati provengano da un file remoto piuttosto che da uno locale. Ecco un esempio di esecuzione dell'applet:

5.8. Conclusione
Questo capitolo ha presentato
- un'introduzione alla creazione di interfacce grafiche con JBuilder
- i componenti Swing più comuni
- la creazione di applet
Ricordiamo che
- il codice generato da JBuilder può essere scritto a mano. Una volta ottenuto questo codice in un modo o nell'altro, basta un semplice JDK per eseguirlo e JBuilder non è quindi più indispensabile.
- l'utilizzo di uno strumento come JBuilder può comportare notevoli aumenti di produttività:
- se è possibile scrivere a mano il codice generato da JBuilder, ciò può richiedere molto tempo e presenta scarso interesse, poiché la logica dell’applicazione risiede in genere altrove.
- Il codice generato può essere istruttivo. Leggerlo e studiarlo è un buon modo per scoprire alcuni metodi e proprietà dei componenti che si utilizzano per la prima volta.
- JBuilder è multipiattaforma. Si mantengono quindi le competenze acquisite passando da una piattaforma all’altra. La possibilità di scrivere programmi che funzionano sia su Windows che su Linux è ovviamente un fattore di produttività molto importante. Tuttavia, ciò è dovuto a Java stesso e non a JBuilder.
5.9. JBuilder su Linux
Tutti gli esempi precedenti sono stati testati su Windows 98. Ci si può chiedere se i programmi scritti siano portabili così come sono su Linux. A condizione che la macchina Linux in questione disponga delle classi utilizzate dai vari programmi, lo sono. Se, ad esempio, avete installato JBuilder su Linux, le classi necessarie sono già presenti sulla vostra macchina. Ecco, ad esempio, il risultato dell’esecuzione di uno dei nostri programmi sul componente JList con JBuilder 4 su Linux:
Di seguito illustriamo l’installazione di JBuilder 4 Foundation su un computer Linux. La sua installazione su un computer Win9x non presenta alcun problema ed è analoga alla procedura che verrà ora descritta. L’installazione delle versioni successive è probabilmente diversa, ma questo documento può comunque fornire alcune informazioni utili.
JBuilder è disponibile sul sito di Inprise all'indirizzo http://www.inprise.com/jbuilder

In questa pagina sono presenti i link, in particolare per Windows e Linux. Descriviamo ora l’installazione di JBuilder su un computer Linux dotato dell’interfaccia grafica KDE.
Seguendo il link «Jbuilder 4 for Linux», viene visualizzato un modulo. Una volta compilato, si ottengono due file:
jb4docs_fr.tar.gz: la documentazione e gli esempi di Jbuilder4
jb4fndlinux_fr.tar.gz: JBuilder 4 Foundation. Si tratta di una versione limitata del JBuilder 4 commerciale, ma sufficiente in un contesto didattico.
Una chiave di attivazione del software vi verrà inviata via e-mail. Essa vi consentirà di utilizzare JBuilder 4 e vi verrà richiesta al primo utilizzo. Se perdete questa chiave, potete tornare all’URL sopra indicato e seguire il link “get your activation key”. Diamo per scontato che ora siate root e che vi troviate nella directory dei due file tar.gz sopra indicati. Decomprimete i due file:
[ls -l]
drwxr-xr-x 3 nobody nobody 4096 oct 10 2000 docs
drwxr-xr-x 3 nobody nobody 4096 déc 5 13:00 foundation
[ls -l foundation]
-rw-r--r-- 1 nobody nobody 1128 déc 5 13:00 deploy.txt
-rwxr-xr-x 1 nobody nobody 69035365 déc 5 13:00 fnd_linux_install.bin
drwxr-xr-x 2 nobody nobody 4096 déc 5 13:00 images
-rw-r--r-- 1 nobody nobody 15114 déc 5 13:00 index.html
-rw-r--r-- 1 nobody nobody 23779 déc 5 13:00 license.txt
-rw-r--r-- 1 nobody nobody 75739 déc 5 13:00 release_notes.html
-rw-r--r-- 1 nobody nobody 31902 déc 5 13:00 whatsnew.html
[ls -l docs]
-rw-r--r-- 1 nobody nobody 1128 oct 10 2000 deploy.txt
-rwxr-xr-x 1 nobody nobody 40497874 oct 10 2000 doc_install.bin
drwxr-xr-x 2 nobody nobody 4096 oct 10 2000 images
-rw-r--r-- 1 nobody nobody 9210 oct 10 2000 index.html
-rw-r--r-- 1 nobody nobody 23779 oct 10 2000 license.txt
-rw-r--r-- 1 nobody nobody 75739 oct 10 2000 release_notes.html
-rw-r--r-- 1 nobody nobody 31902 oct 10 2000 whatsnew.html
Nelle due cartelle generate, il file .bin è il file di installazione. Inoltre, aprite con un browser il file index.html presente in ciascuna delle due cartelle. Questi file forniscono le istruzioni da seguire per installare entrambi i prodotti. Iniziamo con l'installazione di JBuilder Foundation:
Viene visualizzata la prima schermata dell’installazione. Ne seguiranno molte altre:

Confermare. Segue una schermata esplicativa:

Eseguire [suivant].

Accettare il contratto di licenza ed eseguire [suivant].

Accetta la posizione proposta per JBuilder (prendine nota, ti servirà in seguito) e digita [suivant]. L'installazione richiede poco tempo.

Siamo pronti per un primo test. In KDE, avviate il gestore dei file per accedere alla directory degli eseguibili di JBuilder: /opt/jbuilder4/bin (se avete installato JBuilder in /opt/jbuilder4):

Fare clic sull’icona jbuilder qui sopra. Poiché è la prima volta che si utilizza JBuilder, sarà necessario inserire la chiave di attivazione:

Compilate i campi Nom e Société. Selezionare [Ajouter] per inserire la chiave di attivazione. Si ricorda che questa dovrebbe esservi stata inviata via e-mail e che, se l’avete smarrita, potete recuperarla all’indirizzo URL da cui avete scaricato JBuilder 4 (cfr. inizio dell’installazione). Una volta accettata la chiave di attivazione, vi verranno ricordate le condizioni di licenza:

Digitando OK, tornerete alla finestra di inserimento dei dati già vista in precedenza:

Digitare OK per completare questa fase, che viene eseguita solo al primo avvio. Successivamente apparirà l’ambiente di sviluppo di JBuilder:

Chiudete JBuilder per procedere all’installazione della documentazione. Questa operazione installerà una serie di file che verranno utilizzati nella guida di JBuilder, che al momento è incompleta. Tornate nella directory in cui avete decompresso i file tar.gz di JBuilder. Il programma di installazione si trova nella directory docs. Accedeteci:
[cd docs]
[ls -l]
-rw-r--r-- 1 nobody nobody 1128 oct 10 2000 deploy.txt
-rwxr-xr-x 1 nobody nobody 40497874 oct 10 2000 doc_install.bin
drwxr-xr-x 2 nobody nobody 4096 oct 10 2000 images
-rw-r--r-- 1 nobody nobody 9210 oct 10 2000 index.html
-rw-r--r-- 1 nobody nobody 23779 oct 10 2000 license.txt
-rw-r--r-- 1 nobody nobody 75739 oct 10 2000 release_notes.html
-rw-r--r-- 1 nobody nobody 31902 oct 10 2000 whatsnew.html
Il file di installazione è doc_install.bin, ma non è possibile eseguirlo immediatamente. Se lo si fa, l'installazione fallisce senza che se ne capisca il motivo. Leggere il file index.html con un browser per una descrizione dettagliata della procedura di installazione. Il programma di installazione richiede una macchina virtuale Java, ovvero un programma denominato java, che deve trovarsi nella directory PATH del proprio computer. Si ricorda che PATH è una variabile Unix il cui valore, nella forma rep1:rep2:...:repn, indica le directory repi che devono essere esplorate nella ricerca di un eseguibile. In questo caso, il programma di installazione richiede l'esecuzione di un programma denominato java. È possibile che esistano diverse versioni di questo programma a seconda del numero di macchine virtuali Java installate qua e là. Logicamente, useremo quella fornita da Jbuilder4 e che si trova in /opt/jbuilder4/jdk1.3/bin. Per inserire questa directory nella variabile PATH:
[echo $PATH]
/usr/local/sbin:/usr/sbin:/sbin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin
[export PATH=/opt/jbuilder4/jdk1.3/bin/:$PATH]
[echo $PATH]
/opt/jbuilder4/jdk1.3/bin/:/usr/local/sbin:/usr/sbin:/sbin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin
Ora possiamo avviare l'installazione della documentazione:
Si tratta di un'installazione grafica:

È molto simile a quella di JBuilder Foundation. Pertanto non la descriveremo in dettaglio. C'è una schermata da non perdere:

Normalmente il programma di installazione dovrebbe individuare automaticamente la posizione in cui è stato installato JBuilder Foundation. Pertanto, non modificate le impostazioni predefinite, a meno che non siano errate.
Una volta installata la documentazione, siamo pronti per un nuovo test di JBuilder. Avviate l’applicazione come illustrato in precedenza. Una volta avviato JBuilder, selezionate l’opzione Aiuto/Argomento della guida. Nel riquadro a sinistra, cliccate sul link Tutoriels:

JBuilder viene fornito con una serie di tutorial che vi permetteranno di muovere i primi passi nella programmazione Java. Di seguito abbiamo seguito il tutorial “Creazione di un’applicazione” sopra riportato.

In JBuilder, selezionate File/Nuovo progetto. Una procedura guidata vi mostrerà 3 schermate:

Creeremo una semplice finestra con il titolo "Ciao a tutti". Chiameremo questo progetto coucou. L’esempio è stato eseguito da root. JBuilder propone quindi di raggruppare tutti i progetti in una cartella jbproject all’interno della cartella di connessione di root. Il progetto coucou verrà collocato nella cartella coucou (campo «Nome della cartella del progetto») di jbproject. Eseguire [suivant].

Questa seconda schermata è un riepilogo dei vari percorsi del progetto. Non è necessario modificare nulla. Eseguire [suivant].

La terza schermata vi chiede di personalizzare il vostro progetto. Compilate i campi e selezionate [Terminer].
Ora esegua Fichier/Nouveau:

Scegliete Application e selezionate OK. Una nuova procedura guidata vi mostrerà 2 schermate:

Il campo paquet riporta il nome del progetto. Il campo «classe» richiede il valore nom, che verrà assegnato alla classe principale del progetto. Prendete il nome sopra indicato e inserite [suivant]:

La nostra applicazione comprende una seconda classe Java per la finestra dell'applicazione. Assegnate un nome a questa classe. Il campo Titre corrisponde al titolo che desiderate assegnare a questa finestra. Il riquadro options offre diverse opzioni per la vostra finestra. Selezionatele tutte e inserite [Terminer]. Si tornerà quindi all’ambiente JBuilder, che è stato arricchito con le informazioni fornite per il progetto:

Nella finestra in alto a sinistra (1) è presente l’elenco dei file che compongono il progetto. Tra questi figurano in particolare le due classi .java a cui abbiamo appena assegnato un nome. Nella finestra a destra (2) è presente il codice Java della classe coucouCadre. Nella finestra in basso a sinistra è visibile la struttura (classi, metodi, attributi) del progetto. Il progetto è pronto per essere eseguito. Premere il pulsante 4 in alto oppure selezionare Esegui/Esegui progetto oppure selezionare F9. Dovrebbe apparire la seguente finestra:

Cliccando sull’opzione Aide, dovreste ritrovare le informazioni che avete fornito alle procedure guidate di creazione. Non andremo oltre. È ora il momento di immergervi nei tutorial.
Prima di concludere, mostriamo semplicemente che è possibile utilizzare non JBuilder e la sua interfaccia grafica, ma il JDK che ha portato con sé e che ha collocato in /opt/jbuilder4/jdk1.3. Compilate il seguente file essai1.java:
import java.io.*;
public class essai1{
public static void main(String args[]){
System.out.println("coucou");
System.exit(0);
}
}
Compiliamolo ed eseguiamolo con il JDK di JBuilder:






