MokaByte 52 - Maggio 2001
Foto dell'autore non disponibile
di
Andrea Gini
Corso di Swing
IX parte: Accessori e Decorazioni
Terminata la panoramica sugli oggetti grafici e sui pannelli, e' arrivato il momento di affrontare alcune interessanti caratteristiche di Swing, come l'uso dei bordi e l'impostazione del Look & Feel. Impareremo anche come creare rapidamente un gran numero di finestre di dialogo, per risolvere tutte quelle situazioni in cui si voglia segnalare qualcosa di anomalo all'utente. 

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

Vai alla Home Page di MokaByte
Vai alla prima pagina di questo mese


MokaByte®  è un marchio registrato da MokaByte s.r.l.
Java®, Jini®  e tutti i nomi derivati sono marchi registrati da Sun Microsystems; tutti i diritti riservati
E' vietata la riproduzione anche parziale
Per comunicazioni inviare una mail a
mokainfo@mokabyte.it