JOptionPane
La
classe JOptionPane permette di realizzare facilmente finestre modali di
input, di allarme o di scelta multipla, ossia quel genere di finestre vengono
utilizzate in quelle situazioni in cui sia necessario segnalare un malfunzionamento,
o presentare all'utente un gruppo di scelte su come procedere nell'esecuzione
di un programma.
L'API
JOptionPane mette a disposizione tre tipi di pannelli: Confirm Dialog,
Input Dialog e Message Dialog: il primo tipo di pannello viene usato quando
si deve chiedere all'utente di effettuare una scelta tra un gruppo di possibilita';
il secondo torna utile quando si debba richiedere l'inserimento di una
stringa di testo mentre il terzo viene usato per informare l'utente di
un evento.
La
classe JOptionPane fornisce un gruppo di metodi statici che permettono
di creare facilmente questi pannelli ricorrendo ad una sola riga di codice:
vediamo un esempio di Confirm Dialog
JOptionPane.showConfirmDialog(null,"Salvare
le modifiche?");
Figura
1 - Un pannello di conferma puo' aiutarci ad evitare guai......
ed
uno di di Message Dialog
JOptionPane.showMessageDialog(null,
"Questo programma ha eseguito un'operazione non valida e sara' terminato....",
"Errore", JOptionPane.ERROR_MESSAGE);
Figura
3 - ....un minaccioso pannello di notifica ci annuncia che ormai e' troppo
tardi
Come
si vede non e' stato necessario creare esplicitamente alcun oggetto di
tipo JOptionPane: in entrambi i casi e' bastato richiamare un metodo statico
0che ha provveduto a creare un oggetto grafico con le caratteristiche specificate
dai parametri. In questo paragrafo ci concentreremo sull'utilizzo di un
sottoinsieme di tali metodi, nella convinzione che essi permettano di risolvere
la stragrande maggioranza delle situazioni in modo compatto ed elegante.
static
int showConfirmDialog(Component parentComponent,
Object message):
mostra
una finestra di conferma con le opzioni Yes, No e Cancel e con il titolo
"Select an Option". Il parametro permette di specificare il messaggio.
static
int showConfirmDialog(Component parentComponent,
Object message,
String title,
int optionType,
int messageType)
mostra
una finestra di conferma personalizzata.
static
String showInputDialog(Component parentComponent,
Object message)
mostra
una finestra di input generica.
static
String showInputDialog(Component parentComponent,
Object message,
String title,
int messageType)
mostra
una finestra di input personalizzata.
static
void showMessageDialog(Component parentComponent,
Object message)
mostra
una finestra di informazione dal titolo "Message".
static
void showMessageDialog(Component parentComponent,
Object message,
String title,
int messageType)
mostra
una finestra di informazione personalizzata.
I metodi
appena illustrati richiedono di specificare alcuni dei seguenti parametri:
-
Parent
Component: questo parametro serve a specificare il frame principale; esso
verra' bloccato fino al termine dell'interazione. Ponendo a null questo
parametro, la finestra verra' visualizzata al centro dello schermo e risultera'
indipendente dal resto dell'applicazione.
-
Message:
questo campo permette di specificare una stringa da visualizzare come messaggio.
In alternativa a String si puo' passare una Icon o una qualunque sottoclasse
di Component.
-
OptionType:
i Confirm Dialog possono presentare diversi gruppi di opzioni, e precisamente
-
YES_NO_OPTION
-
YES_NO_CANCEL_OPTION
-
OK_CANCEL_OPTION
-
Message
Type: attraverso questo parametro possiamo influenzare l'aspetto complessivo
della finestra, come il tipo di icona, il titolo, il layout. Esso puo'
assumere uno dei seguenti valori
-
JOptionPane.ERROR_MESSAGE
-
JOptionPane.INFORMATION_MESSAGE
-
JOptionPane.WARNING_MESSAGE
-
JOptionPane.QUESTON_MESSAGE
-
JOptionPane.PLAIN_MESSAGE
Le
finestre create con i metodi showConfirmDialog e showMessageDialog restituiscono
un intero che fornisce informazioni su quale scelta e' stata effettuata
dall'utente. Esso puo' assumere uno dei seguenti valori:
-
JOptionPane.YES_OPTION,
-
JOptionPane.NO_OPTION,
-
JOptionPane.CANCEL_OPTION,
-
JOptionPane.OK_OPTION,
-
JOptionPane.CLOSED_OPTION.
Nel caso
di showInputDialog viene invece restituita una stringa di testo, o null
se l'utente ha annullato l'operazione. Il programmatore puo' prendere decisioni
su come proseguire leggendo ed interpretando la risposta in maniera simile
a copme si vede nell'esempio:
int
returnVal = JOptionPane.showConfirmDialog(null,
"Salvare le modifiche?");
if(returnVal
== JOptionPane.YES_OPTION)
// procedura da eseguire in caso affermativo
else if(returnVal == JOptionPane.NO_OPTION)
// procedura da eseguire in caso negativo
else;
// operazione abortita
Pluggable Look
& Feel
Ogni
ambiente a finestre e' caratterizzato da due fondamentali proprieta': l'aspetto
dei componenti (ovvero la loro sintassi), e la maniera in cui essi
reagiscono alle azioni degli utenti (la loro semantica); l'insieme di queste
proprieta' viene comunemente definito Look & Feel.
Chiunque
abbia provato a lavorare su un sistema Linux dopo anni di pratica su piattaforma
Windows si sara' reso conto di quanto sia difficile abituarsi ad una nuova
semantica: le mani tendono a comportarsi come sulla vecchia piattaforma,
ma la reazione che osserviamo con gli occhi non e' quella che ci aspettavamo:
le finestre si espandono verticalmente invece che a pieno schermo, i menu'
scompaiono quando si rilascia il tasto del mouse e cosi' via.
La
natura multipiattaforma di java ha spinto i progettisti di Swing a separare
le problematiche di disegno grafico dei componenti da quelle inerenti al
loro contenuto informativo, con la sorprendente conseguenza di permettere
agli utenti di considerare il Look & Feel come una proprieta'
del componente da impostare a piacere.
La
distribuzione standard del JDK comprende di base due alternative: Metal
e Motif. La prima definisce un Look & Feel multipiattaforma, progettato
per risultare familiare agli utenti di ogni piattaforma; la seconda implementa
una vista familiare agli utenti Unix. Le distribuzioni di java per Windows
e Mac includono anche un L&F che richiama quello della piattaforma
ospite; per motivi di copiright non e' permesso alla Sun di proporre queste
due scelte su piattaforme diverse. Alcune software house indipendenti distribuiscono,
sotto forma di file JAR, dei package contenenti dei L&F alternativi:
per aggiungerli alla lista dei L&F di sistema e' sufficiente inserire
questi files nel classpath.
Per
impostare da programma un particolare look & feel e' sufficiente chiamare
il metodo UIManager.setLookAndFeel(String className) passando come parametro
il nome di un l&f installato nel sistema, ad esempio:
try
{
UIManager.setLookAndFeel("
javax.swing.plaf.metal.MetalLookAndFeel" );
}
catch (Exception e) { }
Di
seguito presentiamo le stringhe relative ai quattro L&F descritti sopra:
-
"javax.swing.plaf.metal.MetalLookAndFeel"
: specifica il Java Look & Feel, denominatoMetal.
-
"com.sun.java.swing.plaf.windows.WindowsLookAndFeel"
: specifica il Look & Feel
-
Windows,
disponibile solo su piattaforma Win32.
-
"com.sun.java.swing.plaf.motif.MotifLookAndFeel"
: permette di impostare un L&F in stile CDE/Motif. Questa scelta e'
disponibile su qualunque piattaforma
-
"javax.swing.plaf.mac.MacLookAndFeel":
definisce il Look & Feel Mac, disponibile solo su piattaforma Apple
Se si
desidera interrogare il sistema per conoscere il nome e la quantita' dei
L&F installati, possiamo ricorrere ai seguenti metodi statici di UIManager.
-
static
String getSystemLookAndFeelClassName(): restituisce il nome del LookAndFeel
che implementa il sistema a finestre della piattaforma ospite (windows
su sistemi Microsoft, Mac su macchine Apple e Motif su piattaforma Solaris).
Se non esiste una scelta predefinita, viene restituito il nome del Metal
L&F.
-
static
String getCrossPlatformLookAndFeelClassName() : restituisce il nome del
LookAndFeel multipiattaforma, il Java Look and Feel (JLF).
-
static
UIManager.LookAndFeelInfo[] getInstalledLookAndFeels() : restituisce un
vettore di oggetti che forniscono alcune informazioni sui LookAndFeel installati
nel sistema, tra le quali il nome (accessibile con il metodo getName()).
Border
Una
caratteristica che Swing offre in esclusiva e' la possibilita' di assegnare
un bordo diverso ad ogni singolo componente grafico, sia esso un pannello,
un pulsante o una Tool Bar. Per aggiungere un bordo ad un componente, e'
sufficiente chiamare il metodo setBorder(Border b) passando come parametro
un'istanza di una qualunque delle classi descritte di seguito.
Il
package javax.swing.border offre ben sette tipi di bordo, il piu' semplice
dei quali e' composto da una singola riga, dello spessore specificato.
-
LineBorder(Color
color, int thickness, boolean roundedCorners): crea un bordo a linea del
colore, spessore e tipo di bordo specificato.
-
I seguenti
bordi ricreano effetti tridimensionali: essi richiedono come parametro
un intero che puo' assumere il valore BevelBorder.LOWERED o BevelBorder.RAISED
a seconda che si desideri un effetto in rilievo o rientrante.
-
BevelBorder(int
bevelType): crea un bordo in rilievo, del tipo specificato dal parametro.
-
SoftBevelBorder(int
bevelType): crea un bordo in rilievo sfumato, del tipo specificato dal
parametro.
-
EtchedBorder(int
etchType): crea un bordo scolpito, del tipo specificato dal parametro.
Qualora
si desideri creare attorno ad un componente una vera e propria cornice
di spessore arbitrario, e' possibile ricorrere ai seguenti oggetti, che
permettono creare bordi vuoti, a tinta unita o decorati con un'immagine
GIF o JPeg
-
EmptyBorder(int
top, int left, int bottom, int right): crea un bordo vuoto dello spessore
specificato.
-
MatteBorder(Icon
tileIcon): crea un bordo utilizzando un'immagine.
-
MatteBorder(int
top, int left, int bottom, int right, Icon tileIcon): crea un bordo delle
dimensioni specificate utilizzando un'icona.
-
MatteBorder(int
top, int left, int bottom, int right, Color matteColor): crea un bordo
delle dimensioni e del colore specificati.
Per finire,
e' disponibile una coppia di bordi che permette di creare composizioni
di altri bordi
-
TitledBorder(Border
border, String title, int titleJustification, int titlePosition, Font titleFont,
Color titleColor): crea una cornice composta dal bordo che viene passato
come primo parametro e dal titolo specificato dal secondo parametro. Il
terzo parametro puo' assumere i valori TitledBorder.CENTER, TitledBorder.LEFT
o TitledBorder.RIGHT; il quarto, che specifica la posizione del titolo,
puo' assumere invece i valori TitledBorder.ABOVE_BOTTOM, TitledBorder.ABOVE_TOP,
TitledBorder.BELOW_BOTTOM, TitledBorder.BELOW_TOP. Gli ultimi due parametri
specificano il font ed il colore del titolo. Sono disponibili costruttori
piu' semplici, ad esempio uno che richiede solo i primi due parametri ed
uno che omette gli ultimi due.
-
CompoundBorder(Border
outsideBorder, Border insideBorder): Crea una cornice componendo i due
bordi passati come parametro.
Il
prossimo esempio illustra la costruzione di una sottoclasse di TextEditor,
il programma descritto nella sezione relativa a JTextArea. Ridefinendo
i "Factory Metod" possiamo modificare in maniera vistosa l'aspetto dell'applicazione,
aggiungendo un bordo alla MenuBar, alla ToolBar e al pannello centrale,
senza il bisogno di alterare il costruttore del programma.
Figura
3 - aggiungendo i bordi possiamo dare un look piu'
aggressivo
a qualunque applicazione
import
java.awt.*;
import
javax.swing.*;
import
javax.swing.border.*;
public
class BorderedTextEditor extends TextEditor {
protected JMenuBar createMenuBar() {
JMenuBar mb = super.createMenuBar();
mb.setBorder(new MatteBorder(7,12,7,12,
new ImageIcon("Texture_wood_004.jpg")));
mb.setBackground(new Color(224,195,96));
return mb;
}
protected JToolBar createToolBar() {
JToolBar tb = super.createToolBar();
tb.setBorder(new MatteBorder(7,12,7,12,
new ImageIcon("Texture_wood_004.jpg")));
tb.setBackground(new Color(224,195,96));
return tb;
}
protected JComponent createCenterComponent() {
JComponent c = super.createCenterComponent();
c.setBorder(new MatteBorder(7,12,7,12,
new ImageIcon("Texture_wood_004.jpg")));
return c;
}
public static void main(String argv[]) {
BorderedTextEditor t = new BorderedTextEditor();
}
}
Conclusioni
Con
questo articolo termina il corso introduttivo su Swing. In questi nove
appuntamenti abbiamo affrontato tutte le tematiche di base della programmazione
a finestre, e introdotto alcuni argomenti avanzati: ora non resta che mettere
in pratica quanto appreso. L'unico consiglio che mi sento di dare a chi
voglia imparare a scrivere buoni programmi grafici e' di studiare un gran
numero di programmi scritti da programmatori esperti (compreso il codice
delle API Swing), e di cercare di adattarli alle proprie esigenze, senza
aver vergogna a copiare; con il tempo crescera' la sicurezza e la capacita'
di trovare soluzioni originali.
L'esempio
descritto in questo articolo può essere trovato qui |