Sei sulla pagina 1di 26

Prima di iniziare a descrivere l’architettura dei componenti Swing, occorre considerare gli elementi

di un componente dell’interfaccia utente, per esempio un pulsante, una casella di controllo, una
casella di testo. Ogni componente ha tre caratteristiche che lo distinguono:

 Il suo contenuto, per esempio lo stato di un pulsante (premuto o rilasciato) oppure il testo
di una casella di testo.

 Il suo aspetto visivo, cioè il colore, la dimensione così via.

 Il suo comportamento, cioè la reazione agli eventi.

Riflettere sul funzionamento interno e sulle caratteristiche di un componente, è un compito dei


programmatori. Per questo i progettisti Swing hanno adottato un pattern di progetto: il pattern
modello-vista-controllore, o MVC (Model-View-Controller). Questo pattern, come altri pattern di
progetto, si ispira a uno dei principi di programmazione orientata agli oggetti : non si devono
affidare troppe responsabilità a un oggetto. Non è bene che una sola classe pulsante, ad esempio,
faccia tutto. Pertanto si implementano tre classi separate:

 Il modello (model), che memorizza il contenuto

 La vista (view), che visualizza il contenuto

 Il controllore (controller), che gestisce l’input dell’utente

Il pattern definisce con precisione l’interazione tra questi tre oggetti. Uno dei vantaggi di questo
pattern è che un modello può avere viste multiple, ciascuna delle quali mostra una parte o un
aspetto del contenuto completo. Per esempio, un editor HTML può offrire due viste simultanee
dello stesso contenuto. Quando il modello viene aggiornato mediante il controllore di una delle
viste, informa entrambe le viste collegate delle modifiche avvenute. Il controllore gestisce gli
eventi dell’input dell’utente, per esempio i click del mouse e le combinazioni di tasti. Il controllore
stesso decide allora di tradurre questi eventi in modifiche del modello o della vista.
Per esempio, se l’utente preme il tasto di un carattere in una casella di testo, il controllore chiama
il comando “inserisci carattere” del modello. Il modello dice allora alla vista di aggiornarsi. La vista
non sa mai perché il testo è cambiato. Lo scorrimento della vista non ha effetto sul testo
sottostante, e il modello non sa che questo evento si è verificato.
Gestione del Layout

In questo paragrafo si illustrerà come collocare i componenti all’interno di un frame.


In un contenitore tutti i componenti vengono collocati da un gestore di layout.

FlowLayout
Il gestore di layout a flusso (flow layout), è il gestore di layout predefinito per un pannello. I
componenti vengono allineati in senso orizzontale fino a quando c’è spazio sufficiente, poi si inizia
una nuova riga di componenti. Quando l’utente ridimensiona il contenitore, il gestione di layout
ridistribuisce automaticamente i componenti per riempire lo spazio disponibile. E’ anche possibile
scegliere come collocare i componenti su ciascuna riga. L’impostazione predefinita prevede di
centrarli nel contenitore, mentre le altre opzioni riguardano la possibilità di allineare i componenti
nel contenitore lungo il lato sinistro o destro.

 Per impostare uno di questo allineamenti, si deve specificare la costante LEFT o RIGHT nel
costruttore dell’oggetto FlowLayout:

panel.setLayout(new FlowLayout(FlowLayout.LEFT));

 In alternativa è possibile costruire un nuovo FlowLayout con l’allineamento specificato e le


distanze, in pixel, tra i componenti in senso orizzontale e verticale:

panel.setLayout(new FlowLayout(int align, int hgap, int vgap));

I valori negativi di hgap e vgap producono una sovrapposizione.

BorderLayout
Il gestore di layout a bordo (border layout) è il gestore predefinito del pannello dei contenuti di
ogni JFrame. Permette di scegliere dove si vuole collegare ogni componente. Si può scegliere di
collocare il componente al centro, a nord, a sud, a est oppure a ovest del pannello dei contenuti.
Prima si collocano i componenti lungo il bordo, poi lo spazio che rimane è occupato da quelli che
devono risultare centrati. Quando si ridimensiona il contenitore, le dimensione dei componenti sul
bordo non vengono modificare, mentre il componente al centro modifica la sua dimensione.

 Per impostare uno di questi collocamenti, si deve specificare un delle costanti della classe
BorderLayout: CENTER, NORTH, SOUTH, EAST o WEST:

panel.setLayout(new BorderLayout());
panel.add(button, BorderLayout.NORTH);
 In alternative è possibile indicare le distanze in pixel tra le varie aree, impostando il
parametro corrispondente nel costruttore di BorderLayout:

panel.setLayout(new BorderLayout(int hgap, int vgap));

I valori negative di hgap e vgap producono una sovrapposizione.

GridLayout
Il layout a griglia (grid layout) colloca i componenti in righe e colonne, come in un foglio di calcolo.
Inoltre prevede che le celle abbiano tutte la stessa dimensione. Quando si ridimensiona la finestra,
i pulsanti si allargano e si restringono, ma tutti i pulsanti hanno la medesima dimensione.

 Nel costruttore dell’oggetto layout a griglia si specifica il numero di righe e di colonne


desiderato:

panel.setLayout(new GridLayout(5, 4));

 In alternativa è possibile anche specificare le distanze desiderate in senso orizzontale e


verticale tra i componenti:

panel.setLayout(new GridLayout(int row, int column, int hgap, vhap));

I valori negative di hgap e vgap producono una sovrapposizione.


Testo in input

A questo punto si può iniziare a parlare dei componenti Swing dell’interfaccia utente. In
particolare inizieremo a trattare i componenti che permettono a un utente di inserire e modificare
un testo in input. A tal proposito si possono utilizzare i componenti JTextField e JTextArea per
raccogliere il testo in input. Una casella di testo può accettare solo una riga di testo, mentre un’are
di testo può accettare più righe di testo. Entrambe le classi ereditano una classe astratta di nome
JTextComponent.

Casella di testo
Di solito si aggiunge una casella di testo in una finestra inserendola in un pannello o in un altro
contenitore, come si farebbe con un pulsante:

JPanel panel = new JPanel();


JTextField textTfield = new JTextField(“Default Input”, 20);
panel.add(textField);

Questo codice aggiunge una casella di testo e la inizializza collocando la stringa “Default Input” al
suo interno (se si omette il primo parametro si costruire una casella di testo vuota). Il secondo
parametro imposta la larghezza in colonne. Quest’ultima misura è poco attendibile poiché la
misura di una colonna è alquanto imprecisa. Per questo conviene sempre aggiungere 1 o 2 alla
lunghezza massima dell’input. Inoltre la larghezza in colonne non è un limite sul numero di
caratteri che l’utente può inserire. L’utente può sempre digitare una stringa più lunga e quando il
testo supera la lunghezza della casella, l’input scorre.

 Per reimpostare il numero di colonne a runtime, si deve utilizzare il metodo setColumns.

textField.setColumns(10);
panel.revalidate();

Il metodo di rivalidazione (appartenente alla classe JComponent) ricalcola la dimensione e


il layout di tutti i componenti presenti in un contenitore.

 E’ possibile modificare in ogni momento il contenuto della casella di testo utilizzando il


metodo setText:

textField.setText(“Hello!”);
 Per scoprire ciò che l’utente ha digitato si richiama il metodo getText. Questo metodo
restituisce il testo esatto che l’utente ha digitato:

String text = textField.getText();

 Per rimuovere eventuali interlinee e spaziature dei dati presenti n una casella di testo, si
applica il metodo trim al valore restituito da getText:

String text = textField.getText().trim();

 Per modificare il font con il quale appare il testo dell’utente, si utilizza il metodo setFont:

Aree di testo
A volte è necessario che l’input dell’utente occupi più di una riga di testo. SI è già visto che, in
questi casi, si utilizza un’area di testo implementata dal componente JTextArea. L’utente può
digitare una quantità qualsiasi di righe di testo, utilizzando il tasto INVIO per separarle.
Nel costruttore del componente JTextArea si specifica il numero di righe e di colonne dell’area di
testo, come nel seguente esempio:

JTextArea textArea = new JTextArea(8, 40); // 8 righe e 40 colonne

Il parametro columns ha il significato visto in precedenza: se c’è più testo di quello che l’area di
testo può visualizzare, il testo che rimane escluso viene semplicemente tagliato. Si può evitare il
taglio delle righe lunghe impostando un wrapper delle righe:

textArea.setLineWrap(true); // le righe lunghe richiedono un wrapper

Ogni wrapper ha solo un effetto visuale; il testo del documento non viene modificato e nessun
carattere ‘\n’ viene inserito nel testo.

In Swing un area di testo non prevede barre di scorrimento. Se le si vogliono, si deve inserire l’area
di testo in un pannello di scorrimento:

JScrollPane scrollPane = new JScrollPane(textArea);

Il pannello di scorrimento gestisce la vista dell’area di testo. Le barre di scorrimento appaiono


automaticamente se c’è più testo di quello che l’area di testo può visualizzare, mentre scompaiono
altrimenti.
Etichette
Le etichette sono componenti che contengono del testo, non hanno decorazioni, per esempio
sono senza bordi, e non reagiscono all’input dell’utente. E’ possibile utilizzare un’etichetta per
identificare i componenti; per esempio, a differenza dei pulsanti, le caselle di testo non prevedono
etichette per identificarli. Per etichettare un componente che non ne prevede una si deve
ricorrere ad un identificatore.

1. Si costruisce un componente JLabel con il testo corretto

2. Si colloca l’etichetta abbastanza vicina al componente che si vuole identificare, in modo


che l’utente possa vedere che l’etichetta identifica il componente corretto.

Il costruttore di un JLabel permette di specificare il testo o l’icona iniziali e , facoltativamente,


l’allineamento del contenuto. Per identificare l’allineamento si utilizzano le costanti dell’interfaccia
SwingCostants cioè LEFT, RIGHT, CENTER, NORTH, EAST e così via.

JLabel = new JLabel(“Minutes”, SwingConstants.RIGHT);

I metodi setText e setIcon permettono di impostare il testo e l’icona dell’etichetta al runtime.

Caselle password
Le caselle password sono un genere speciale di casella di testo. I caratteri digitati dall’utente non
vengono effettivamente visualizzati. In questo caso, ogni carattere digitato è rappresentato da un
carattere di ripetizione (o echo), di solito un asterisco (*). Per implementare una casella di testo di
questo genere, Swing mette a disposizione una classe JPasswordField con i seguenti metodi:

 JPasswordField(String text, int columns) - [testo da visualizzare, null se non esiste]

 void setEchoChar(char echo) - [imposta il carattere echo]

 char[] getPassword() - *restituisce un’array contenente i caratteri della password+

Per motivi di sicurezza si dovrebbe effettuare la cancellazione del contenuto


dell’array restituito dopo averlo utilizzato. La password non viene restituita come
String perché una stringa rimarrebbe nella macchina virtuale fino a quando non si
esegue la garbage collector.
Componenti di selezione

Si verificano spesso situazioni nelle quali si preferisce offrire agli utenti una serie finita di opzioni
tra le quali scegliere piuttosto che obbligarli a inserire dei dati in una casella di testo. Si vedrà,
quindi, come si programmano le caselle di controllo (checkbox), i pulsanti di opzione (radio
button), le liste di selezione (combo box) e gli slider.

Caselle di controllo
Se si vuole ottenere solo un input del genere “sì” o “no”, si utilizza un componente casella di
controllo. L’utente di solito seleziona la casella facendo click al suo interno e rimuove il segno di
spunta facendo nuovamente click nella casella.

 Le caselle di controllo richiedono un’etichetta a fianco, in modo da identificarne il


significato. Il testo dell’etichetta è assegnato nel costruttore:

JCheckBox checkBox = new JCheckBox(String label);

 Per attivare o meno la casella di controllo si utilizza il metodo setSelected:

bold.setSelected(true);

 Quando l’utente fa click su una casella di controllo, si attiva l’evento azione:

ActionListener listener = . . . ;
bold.addActionListener(listener);

Pulsanti di opzione
In molti casi si richiede che l’utente attivi solo una tra le caselle a disposizione. Quando si attiva
una casella, le altre vengono automaticamente disattivate. Un gruppo di caselle di questo tipo
prende il nome di gruppo di pulsanti di opzione (radio button group):

 Si costruisce un oggetto di tipo ButtonGroup per ogni gruppo di pulsanti, poi si aggiungono
al gruppo di pulsanti oggetti di tipo JRadioButton:

ButtonGroup group = new ButtonGroup();


JRadioButton firstButton = new JRadioButton(String label, boolean state);
group.add(firstButton);

Da osservare che il gruppo di pulsanti controlla solo il comportamento dei pulsanti.


 Per sapere se un pulsante è stato selezionato, come per le caselle di controllo, si utilizza il
seguente metodo:

firstButton.isSelected();

Bordi
Se si dispongono diversi gruppi di pulsanti di opzione in una finestra di solito si vuole distinguere
visivamente di quale gruppo fa parte ciascuno di essi. Swing offre un set di bordi da utilizzare per
questo scopo. E’ possibile applicare un bordo a un qualsiasi componente che estenda
JComponent. L’utilizzo più comune consiste nel definire un bordo attorno al pannello e riempire il
pannello con altri elementi dell’interfaccia utente.

1. Si chiama il metodo statico di BorderFactory per creare un bordo. Si può scegliere uno dei
seguenti stili:

1. Lowered bevel (bassorilievo)


2. Raised bevel (altorilievo)
3. Etched (incassato)
4. Line (linea)
5. Matte (opaco)
6. Empty (solo per creare uno spazio vuoto attorno al componente)

2. Se si preferisce, si può aggiungere un titolo al bordo passando il bordo stesso a


BorderFactory.createTitleBorder

3. Se si vogliono utilizzare tutte le possibilità, si possono combinare due diversi bordi con una
chiamata BorderFactory.createCompoundBorder(border1, border2). Il primo argomento
specifica l’outer border, il secondo l’inner.

4. Si aggiunge il bordo risultante al componente chiamando il metodo setBorder della classe


JComponent

 Di seguito è indicato come si aggiunge in un pannello un bordo incassato con un titolo:

Border etched = BorderFactory.createEtchedBorder();


Border title = BorderFactory.createTitleBorder(etched, “Title”);
panel.setBorder(titled);
Caselle Combinate
Se si vogliono predisporre più alternative, i pulsanti di opzione non sono la soluzione ideale in
quanto richiedono troppo spazio sullo schermo. Conviene allora utilizzare una casella combinata
(combo box). Quando si fa click su questo componente, compare un elenco di voci e l’utente può
sceglierne una. Se la casella dell’elenco è impostata modificabile, la selezione corrente può essere
modificata come se si trattasse di una casella di testo.

La classe JComboBox mette a disposizione il componente della casella combinata.

 Si chiama il metodo setEditable per rendere modificabile la casella combinata. La modifica


avviene solo nella voce corrente e non modifica il contenuto dell’elenco.

 Si può richiamare la selezione corrente o il testo modificato chiamando il metodo


getSelectedItem.

 Le voci da selezionare vengono aggiunte con il metodo addItem.

 Si possono aggiungere nuove voci in una posizione qualsiasi dell’elenco con il metodo
insertItemAt.

 Se è necessario eliminare delle voci in runtime, si utilizza il metodo removeItem oppure


removeItemAt.

 Il metodo removeAllItems elimina tutte le voci contemporaneamente.

JComboBox faceCombo = new JComboBox();


faceCombo.setEditable(true);
faceCombo.addItem(String title);
facecombo.insertItemAt(String title, int index); //aggiunge all’inizio

Si possono aggiungere voci di ogni tipo; la casella combinata richiama il metodo toString di
ciascuna voce per visualizzarla.
Slider
Le caselle combinate permettono agli utenti di scegliere in un set discreto di valori. Gli slider
permettono invece di scegliere in un set continuo di valori per esempio un numero compreso tra 1
e 100.
 Il metodo più comune per costruire uno slider è indicato di seguito:

JSlider slider = new JSlider(min, max, initialValue);

Se si omettono i valori minimo, massimo e iniziale, vengono inizializzati rispettivamente


con i valori 0, 100, 50;

 Si può anche decidere di collocare lo slider in senso verticale, chiamando il costruttore


indicato di seguito:

JSlider slider = new JSlider(SwingCostants.VERTICAL, min, max, initialValue);

Se l’utente fa scorrere la barra dello slider, il valore dello slider passa dal valore minimo a quello
Massimo con continuità. Quando si cambia il valore si invia un ChangeEvent a tutti i listener di
modifica.

 Per essere avvisati quando avviene un cambiamento si deve aggiungere un oggetto che
implementi l’interfaccia ChangeListener mediale il metodo addChangeListener. Questa
interfaccia ha un solo metodo, stateChanged, che rileva il valore dello slider:

public void stateChange(ChangeEvent event) {


JSlider slider = (JSlider) event.getSource();
int value = slider.getValue();
}

 Si può migliorare l’aspetto dello slider aggiungendo una serie di tacche. Per esempio:

slider.setMajorTickSpacing(20);
slider.setMinorTickSpacing(5);

Lo slider viene decorato con tacche più grandi ogni 20 unità e con tacche più piccole ogni 5
unità. Le unità fanno riferimento ai valori dello slider, non hai pixel.

 Queste istruzioni impostano solo le unità delle tacche. Per renderle visibili si deve chiamare
la seguente istruzione:

slider.setPaintTicks(true);
 Si può obbligare lo slider ad agganciarsi alle tacche. Ogni volta che l’utente smette di
trascinare lo slider in questa modalità, la barra si sposta sulla tacca più vicina. Questa
modalità viene attivata con la seguente istruzione:

slider.setSnapToTicks(true);

 Si possono indicare delle etichette di marcatura delle tacche chiamando la seguente


istruzione:

slider.setPaintLabels(true);

Le etichette possono essere, oltre che numeri, di altri tipi per esempio stringhe o icone
anche se la procedura è un po’ contorta. L’autoboxing facilita questo compito:

1. E’ necessario riempire una tabella hash con chiavi di tipi Integer (valore della tacca)
e valori di tipo Component (di solito si utilizzano oggetti JLabel).

2. A questo punto si chiama il metodo setLabelTable. i Componenti vengono


posizionati sotto i segni delle tacche.

Di seguito è indicato come definire le etichette A, B, C, D, E e F:

HashTable<Integer, Component> labelTable = new HashTable<Integer, Component>();


labelTable.put(0, new JLabel(“A”));
...
labelTable.put(100, new JLabel(“F”));
slider.setTable(labelTable);

 Per eliminare la “scia” dello slider che si sposta, si chiama la seguente istruzione:

slider.setPaintTrack(false);

 Per impostare la direzione inversa dello slider si utilizza la seguente chiamata:

slider.setInverted(true);
Il componente JSpinner
Il componente JSpinner è una casella di testo con due piccoli pulsanti su un lato. Quando si fa click
sui pulsanti, il valore della casella di testo viene incrementato o decrementato. I valori dello
spinner possono essere numeri, date, valori di un elenco oppure, come nella maggior parte dei
casi, una sequenza qualsiasi di valori rispetto ai quali è possibile determinare i valori precedenti e
successivi.
L’impostazione predefinita prevede che lo spinner sia costituito da interi e che i pulsanti
definiscano incremento e decrementi di 1.

 Si ottiene il valore corrente chiamando il metodo getValue che restituisce un Object. Per
questo oggetto va definito un cast Integer e si recupera il valore tramite il wrapper
corrispondente:

JSpinner defaultSpinner = new JSpinner();


...
int value = (Integer) defaultSpinner.getValue();

 E’ possibile modificare l’incremento con un valore diverso da 1 e si possono indicare i limiti


inferiore e superiore che i valori possono assumere.
Si consideri il seguente esempio di uno spinner che inizia con il valore 5, assume valori che
vanno da 0 a 10 e prevede un incremento di 0.5:

JSpinner boundedSpinner = new JSpinner(new SpinnerNumberModel(5,0,10,0.5));

Sono disponibili due costruttore SpinnerNumberModel, uno con parametri int e l’altro con
parametri double. Nel caso in cui anche uno solo dei parametri sia un numero a virgola
mobile si utilizza il secondo costruttore.

Gli spinner non si limitano a utilizzare valori numerici. Si può impostare uno spinner in grado di
replicare una collezione qualsiasi di valori. E’ sufficiente passare uno SpinnerListModel al
costruttore JSpinner. Per esempio:

 Si può costruire un oggetto SpinnerListModel da un array o da una classe che implementa


l’interfaccia List (per esempio ArrayList). Nel programma d’esempio si visualizza uno
spinner che propone un elenco dei nomi di font disponibili:

String[] fonts =
GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyName();
JSpinner listSpinner = new JSpinner(new SpinnerListModel(fonts);
 Un altro utilizzo comodo dello spinner riguarda le date che l’utente può incrementare o
decrementare. Uno spinner di questo tipo viene inizializzato con la data odierna mediante
la seguente chiamata:

JSpinner dateSpinner = new JSpinner(new SpinnerDateModel());

 Per definire un proprio modello si estende la classe AbstractSpinnerModel e si definiscono


I Quattro metodi indicate di seguito:

Object getValue() void setValue(Object value)


Object getNextValue() Object getPreviousValue()
Menu

Swing supporta anche un altro tipo di elementi molto diffuso nelle interface utente: I menu a
discesa. Una barra dei menu nella parte superiore della finestra contiene i nomi dei menu a
discesa. Facendo click su un nome si apre il nume che contiene le voci di menu e i menu secondari.
Quando l’utente fa click su una voce di menu, si chiudono tutti i menu e si invia un messaggio al
programma.

Costruire i menu e aggiungere gli item


La costruzione dei menu è diretta. Per creare una barra dei menu si utilizza:

JMenuBar = menuBar = new JMenuBar();

Una barra dei menu è semplicemente un componente che può essere aggiunto nella posizione
desiderata, di solito si vuole che compaia nella parte superiore di un frame.

 Per aggiungere la barra menu si utilizza il metodo setJMenuBar:

frame.setJMenuBar(menuBar);

 Per ogni menu si crea un oggetto menu:

JMenu editMenu = new JMenu(“Edit”);

 Si aggiungono i menu di livello superiore nella barra dei menu:

menuBar.add(editMenu);

 Si aggiungono le voci di menu, i separatori e i menu secondari all’oggetto menu:

JMenuItem pasteItem = new JMenuItem(“Paste”);


editMenu.add(pasteItem);
editMenu.addSeparator();
JMenu optionsMenu = . . . ; // un menu secondario
editMenu.add(optionsMenu);

 Quando l’utente seleziona un menuItem, si attiva un evento azione. E’ necessario installare


un listener di azione per ogni voce di menu:

ActionListener lister = . . . ;
pasteItem.addActionListener(listener);
 Il metodo add(String s) della classe JMenu permette di aggiungere facilmente una voce di
menu alla fine di un menu e inoltre restituisce la voce di menu appena creata come
nell’esempio:

JMenuItem pasteItem = editMenu.add(“Paste”);


pasteItem.addActionListener(listener);

 E’ inoltre possibile creare voci di menu formate da caselle di controllo o pulsanti di opzione
all’interno di un menu

JCheckBoxMenuItem readonlyItem = new JCheckBoxMenuItem(“Read-Only”);


ButtonGroup group = new ButtonGroup();
JRadioButtonMenuIitem insertItem = new JRadioButtonMenuItem(“Insert”);
JRadioButtonMenuIitem overtypeItem = new
JRadioButtonMenuItem(“Overtype”);
group.add(insertItem);
group.add(overtypeItem);
optionsMenu.add(inertItem);
optionsMenu.add(overtypeItem);
optionsMenu.add(readonlyItem);

Icone nelle voci di menu


Analogamente ai pulsanti, i menu possono avere solo un’etichetta di testo, solo un’icona o
entrambi gli elementi.

 E’ possibile specificare l’icona nel costruttore come segue:

JMenuItem cutItem = new JMenuItem(“Cut”, new ImageIcon(“cut.gif”);

 Oppure la si può impostare con il metodo setIcon

cutItem.setIcon(“cut.gif”);
Menu pop-up

Un menu pop-up è un menu che non è collegato a una barra dei menu ma si può trovare in una
qualsiasi posizione.

 Si crea un menu pop-up in modo analogo a come si crea un menu normale, ma un menu
pop-up non prevede un titolo:

JPopupMenu popup = new JPopupMenu();

 Le voci di menu vengono aggiunte nel solito modo:

JMenuItem item = new JMenuItem(“label”);


item.addActionListener(listener);
popup.add(item);

 Si può visualizzare un menu popup utilizzando il metodo show, specificando come


parametri, il componente genitore e la posizione del menu pop-up, utilizzando il sistema di
coordinate del genitore, come nel seguente esempio:

popup.show(panel, x, y);

Di solito si imposta un menu pop-up in modo che compaia quando l’utente fa click su un
determinato pulsante del mouse (il cosiddetto menu contestuale). Ad esempio in Windows
corrisponde al pulsante secondario del mouse (solitamente quello destro).

 Per definire un menu pop-up quando l’utente fa clic su un componente, impostando un


menu contestuale, si chiama semplicemente il seguente metodo:

component.setComponentPopupMenu(true);
Mnemonici da tastiera
L’utente esperto trova molto comodo selezionare i menu e le voci di menu mediante mnemonici
da tastiera (mnemonic).

 Si può collegare uno mnemonico a un menu chiamando il metodo setMnemonic:

JMenu helpMenu = new JMenu(“Help”);


helpMenu.setMnemonic(‘H’);

Per selezionare un menu di livello superiore dalla barra dei menu, si preme il tasto ALT
insieme alla lettera mnemonica. Per esempio, si preme ALT+H per selezionare il menu Help.

 Si possono definire mnemonici da tastiera per le voci di menu specificando una lettera nel
costruttore della voce di menu:

JMenuItem cutItem = new JMenuItem(“Cut”, ‘T’);

 Se è presente un oggetto Action, si può aggiungere lo mnemonico come valore del tasto
Action MNEMONIC_KEY, come indicato di seguito:

cutAction.putValue(Action.MNEMONIC_KEY, new Integer(‘T’);

Il carattere mnemonico da tastiera viene visualizzato automaticamente nel menu, con la lettera
sottolineata. Quando si visualizza il menu, l’utente deve solo premere il tasto T per selezionare la
voce corrispondente.

Può accadere di non voler sottolineare la prima lettera della voce di menu che coincide con la
lettera mnemonica. Per esempio, se si imposta la lettera “A” per la voce di menu ”Save As”, ha più
senso sottolineare la seconda “A” (Save As).

 Si può specificare il carattere che si vuole sottolineare chiamando il seguente metodo:

cutItem.setDisplayedMnemonicIndex(5);
Acceleratori da tastiera
Gli mnemonici da tastiera permettono di selezionare un menu secondario o una voce di menu dal
menu aperto. Al contrario gli acceleratori (accelerator) sono scorciatoie da tastiera che
permettono di selezionare voci di menu senza aprire il menu corrispondente. Per esempio, molti
programmi collegano gli acceleratori CTRL+O e CTRL+S in corrispondenza delle voci Open e Save
dal menu File.

 Per collegare un acceleratore a una voce di menu si utilizza il metodo setAccelerator che
prende come parametro un oggetto di tipo KeyStroke. Per esempio la seguente chiamata
collega l’acceleratore CTRL+O alla voce di menu openItem:

openItem.setAccelerator(KeyStroke.getKeyStroke(“ctrl O”);

Si possono collegare gli acceleratori sono alle voci di menu, non ai menu. In effetti gli
acceleratori, non aprono il menu, ma attivano direttamente l’evento azione a esso
associato.
Barre degli strumenti
Ciò che rende speciali le barre degli strumenti è che si possono spostare in una posizione, per
esempio lungo uno dei quattro bordi del frame. Quando si rilascia il pulsante del mouse, la barra
degli strumenti viene collocata nella nuova posizione. Inoltre può anche essere completamente
sganciata dal frame; in questo caso è contenuta in un suo frame. Quando si chiude un frame che
contiene una barra degli strumenti sganciata, la barra ritorna nel frame originale.

 Per creare una barra degli strumenti e per aggiungere un componente all’interno:

JToolBar bar = new JToolBar();

oppure si specifica una stringa titolo che deve comparire quando la barra degli strumenti
non è agganciata ai bordi:

JToolBar bar = new JToolBar(title);


bar.add(blueBotton);

oppure si può aggiungere un oggetto Action che mostra la piccola icona dell’azione:

bar.add(blueAction)

 Per separare gruppi di pulsanti:

bar.addSeparator();

 Per avere una barra degli strumenti posizionata in verticale:

bar = new JToolBar(title) //(facoltativo) , SwingCostants.VERTICAL)

I pulsanti sono i component più comuni all’interno delle barre degli strumenti, ma non ci sono
limitazioni nei component che si possono aggiungere. Per esempio, si può aggiungere una casella
combinata.
Suggerimenti
Uno svantaggio delle barre degli strumenti è che gli utenti possono confondere il significato delle
piccole icone che si trovano su di esse, Per risolvere questo problema è progettisti delle interfacce
hanno inventato i suggerimenti (tooltip). Un suggerimento vinee attivato quando il cursore si
ferma per qualche istante sopra un pulsante. Quando l’utente allontana il mouse, il suggerimento
viene rimosso.

 Si possono aggiungere i suggerimenti in qualsiasi JComponent chiamando semplicemente il


metodo setToolTipText:

exitButton.setToolTipText(“Exit”);

oppure, se si utilizzano oggetti Action si associa il suggerimento con il tasto


SHORT_DESCRIPTION :

exitAction.putValue(Action.SHORT_DESCRIPTION, “Exit”);
Finestre di dialogo

Finora tutti I component dell’interfaccia utente sono stati fatti comparire in un frame creato
dall’applicazione. Questa è la situazione più comune se si scrivono applet da eseguire in un
browser web. Se invece si scrivono applicazioni, è preferibile distinguere le finestre di dialogo per
fornire o acquisire informazioni dall’utente.
Analogamente alla maggior parte dei sistemi a finestre, AWT distingue tra finestre di dialogo
modali e non modali. Una finestra di dialogo modale non permette agli utenti di interagire con le
altre finestre dell’applicazione fintanto che la si utilizza; viene utilizzata quando è necessario
ricavare determinate informazioni dall’utente prima di proseguire con l’esecuzione del
programma. Una finestra di dialogo non modale, invece permette all’utente di digitare
informazioni nella finestra e nel resto dell’applicazione. Un esempio di finestra di dialogo non
modale è rappresentato dalla barra degli strumenti.

JOptionPane

Swing prevede una classe JOptionPane, che permette di realizzare una semplici finestre di dialogo
modali: prevede un set di finestre che possono bastare quando è necessario chiedere all’utente
una singola informazione.

 La classe JOptionPane ha quattro metodi statici che mostrano queste finestre di dialogo:

nome metodo descrizione valori restituiti


void showMessageDialog Mostra un messaggio e aspetta void
che l’utente faccia clic su OK.
OK_OPTION
Mostra un messaggio e aspetta CANCEL_OPTION
int showConfirmDialog una conferma, del tipo OK/Cancel. YES_OPTION
NO_OPTION
CLOSED_OPTION
int showOptionDialog Mostra un messaggio e acquisisce Restituisce l’indice
un’opzione dell’utente da un set di dell’opzione selezionata
opzioni. dall’utente oppure
CLOSED_OPTION
String showInputDialog Mostra un messaggio e acquisisce
una riga di input dell’utente. Stringa inserita in input.

Quando si chiama showConfirmDialog è possibile scegliere tra quattro tipi di opzione:

DEFAULT_OPTION YES_NO_OPTION
YES_NO_CANCEL_OPTION OK_CANCEL_OPTION

 Ognuno di questi metodi prevede come primo parametro il componente genitore, che si
può comunque settare a null qualora non dovesse esserci.
 Una tipica finestra di dialogo, ha i seguenti componenti:

1. un’icona sul lato sinistro che dipende da uno dei seguenti cinque tipi di messaggi:

ERROR_MESSAGE (errore) INFORMATION_MESSAGE (info)


WARNING_MESSAGE (avvertimento) QUESTION_MESSAGE (domanda)
PLAIN_MESSAGE (non ha icona)

2. un messaggio che può essere:

 Stringa: disegna la stringa


 Icona: mostra l’icona
 Componente: mostra il componente
 Array dei suddetti elementi: mostra il toString di ciascun elemento
dell’array

3. uno o più pulsanti di opzione

Inoltre può avere un componente aggiuntivo per l’input dell’utente; per esempio una
casella di testo oppure una casella combinata.
JFileChooser
Quando si scrive un’applicazione si vuole spesso essere in grado di aprire e salvare dei file. Swing
propone una classe JFileChooser che permette di visualizzare una finestra di dialogo modale per la
selezione dei file simile a quella utilizzata dalla maggior parte delle applicazioni native.
I passi necessari per realizzare una finestra di dialogo sono:

1) Si costruisce un oggetto JFileChooser. Non si deve indicare il componente genitore nel


costruttore cosicché si possa utilizzare lo stesso oggetto in diversi frame:

JFileChooser chooser = new JFileChooser();

2) Si imposta la directory chiamando il metodo setCurrentDirectory; per esempio, se si vuole


utilizzare la directory di lavoro corrente:

chooser.setCurrentDirectory(new File(“.”));

Ciò che si deve sapere per ora dell’oggetto File è che il costruttore File(String filename)
trasforma un file o una directory in un oggetto File.

3) Se è previsto un nome predefinito che ci si aspetta venga scelto dall’utente, lo si può


impostare con il metodo setSelectedFile:

chooser.setSelectedFile(new File(filename));

4) Per consentire all’utente di selezionare più file nella finestra di dialogo, si chiama il metodo
setMultiSelectionEnabled(true); questa opzione è facoltativa

5) Si può impostare un filtro di file (vedere paragrafo successivo)

6) L’impostazione predefinita prevede che l’utente possa selezionare solo i file. Se si vuole che
l’utente possa selezionare le directory si chiama il metodo setFileSelectionMode:

 chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);

 chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

 chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
7) Non essendo una sottoclasse di JDialog, invece di chiamare setVisible(true) si chiamano i
metodi showOpenDialog oppure showSaveDialog. In queste chiamate si deve definire il
componente genitore:

int result = chooser.showOpenDialog(parent);

int result = choose.showSaveDialog(parent);

 Per modificare l’etichetta standard del “pulsante di conferma” (Open/Save), si può


chiamare il metodo showDialog e passare un testo esplicito per questo pulsante:

int result = choose.showDialog(parent, “Select”);

Queste chiamate restituiscono un valore intero quale:

 JFileChooser.APPROVE_OPTION se l’utente ha confermato la finestra di dialogo

 JFileChooser.CANCEL_OPTION se l’utente ha cancellato la finestra di dialogo

 JFileChooser.ERROR_OPTION se l’utente ha abbandonato la finestra di dialogo

8) Si acquisisce il file (o i file) selezionato con il metodo getSelectedFile() o getSelectedFiles(),


i quali restituiscono rispettivamente un singolo oggetto File oppure un array di oggetti File.
Se è necessario indicare solo il nome dell’oggetto file, si chiama il metodo getPath:

File file = chooser.getSelectedFile();


File[] file = chooser.getSelectedFiles();
String filename = chooser.getSelectedFile().getPath();
Choosable file filter
La difficoltà maggiore nell’utilizzare una finestra di dialogo consiste nell’indicare un sottoinsieme
di file rispetto ai quali l’utente può effettuare la selezione. In questo caso si deve fornire all’utente
una forma di feedback che segnali il fatto che i file visualizzati appartengono a una determinata
categoria. I progettisti del selettore di file hanno creato un meccanismo elegante: per limitare i file
visualizzati si definisce un oggetto che estende la classe astratta javax.swing.filechooser.FileFilter.
Il selettore di file scorre ogni file e visualizza solo quelli accettati dal filtro.

 La classe FileFilter definisce due metodi astratti che vanno ridefiniti nella sottoclasse:

boolean accept(File f)
String getDescription()

Il primo deve restituire true se il File f deve essere accettato e quindi visualizzato, false se
invece deve essere ignorato. Il secondo serve per fornire la descrizione che JFileChooser
visualizza nell’elenco dei filtri selezionabili dall’utente.

 Un esempio di filtro "cablato" per visualizzare solo i file .txt è questo:

public TxtFilter extends FileFilter {


public boolean accept(File f) {
if(f.isDirectory())
return true; // accetta sempre le directory
String filename = f.getName();
return extension.endsWith(“.txt”);
}
public String getDescription() {
return “File di testo (*.txt)”;
}
}

 E’ possibile installare più filtri nel selettore di file chiamando:

chooser.addChooSableFileFilter(new TxtFilter());

 Se si vuole si può realizzare una classe più generica, in modo che possa essere facilmente
riutilizzata per estensioni differenti passando al costruttore la Stringa dell’estensione che si
vuole filtrare e la Stringa della descrizione che si vuole far apparire

chooser.addChoosableFileFilter(new GeneralFilter(“File di testo”, “.txt”));


chooser.addChoosableFileFilter(new GeneralFilter(“File JPG”, “.jpg”));
 A partire da Java 6 è stata aggiunta una classe FileNameExtensionFilter che accetta una
descrizione e un array di estensioni. Essendo disponibile da Java 6, il costruttore sfrutta
utilmente i “var-args” cioè può avere un numero variabile di argomenti. Per esempio:

FileFilter txtFilter = new FileNameExtensionFilter("File di testo", "txt");


FileFilter jpegFilter = new FileNameExtensionFilter("File JPEG", "jpg", "jpeg");

Selettore di colori
Un altro selettore fornito da Swing è JColorChooser. Questo selettore viene utilizzare per scegliere
il valore di un colore; inoltre contiene metodi per creare finestre di dialogo che lo contengano.

 Di seguito è riportato come si visualizza una finestra di dialogo modale per il selettore di
colori:

Color selectedColor = JColorChooser.showDialog(parent, title, initialColor);

 In alternative si può visualizzare una finestra di dialogo non modale relativa a un selettore
di colori:

1. un componente genitore
2. il titolo della finestra di dialogo
3. un flag per selezionare una finestra di dialogo modale o non modale
4. un selettore di colori
5. listener per i pulsanti OK e Cancel, oppure null se non si vuole un listener

 L’esempio di seguito costruisce una finestra di dialogo non modale che imposta il colore di
sfondo quando l’utente fa clic sul pulsante OK:

chooser = newJColorChooser();
dialog = JColorChooser.createDialog
(parent, “Background Color”, false, chooser,
new ActionListener() {
public void actionPerformed(ActionEvent event) {
setBackground(chooser.getColor());
}
}, null);
// l’ultimo parametro null significa che non c’è il listener del pulsante cancel

Potrebbero piacerti anche