La prima applicazione Swing
Finalmente, dopo tanta fatica, siamo arrivati alla realizzazione della nostra prima applicazione con le Swing. Come annunciato all'inizio della serie di articoli, creeremo una piccola applicazione che ci permetta di vedere quali sono i vari LookAndFeel disponibili, dando la possibilità di passare tra uno e l'altro.
Per fare questo esaminiamo nel dettaglio il listato seguente.
package corso.swing.capitolo3;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
/**
* Questa classe permette la visualizzazione di un piccolo JFrame
* all'interno del quale mettiamo una piccola choice attraverso
* la quale scegliamo il PL&F dello stesso.
*
* @author Massimo Carli
* @version 0.1 (09/02/1999)
*/
public class PlafJFrame extends JFrame {
/** Crea il Frame e la relativa interfaccia grafica. */
public PlafJFrame() {
super("PlafJFrame");
/* Prendiamo le informazioni relative ai L&F disponibili. */
final UIManager.LookAndFeelInfo[] plaf_disponibili =
UIManager.getInstalledLookAndFeels();
/* Creiamo una JComboBox con i PLAF disponibili. */
String[] nomi_plaf = new String[plaf_disponibili.length];
for (int i = 0; i < plaf_disponibili.length; i++)
nomi_plaf[i] = plaf_disponibili[i].getName();
JComboBox combo = new JComboBox(nomi_plaf);
/* Componiamo l'interfaccia su un JPanel. */
final JPanel panel = new JPanel();
panel.add(combo);
getContentPane().add(panel);
/* Ascoltiamo la combo e modifichiamo il L&F. */
combo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int indice = ((JComboBox)e.getSource()).getSelectedIndex();
String nome_classe_plaf =
plaf_disponibili[indice].getClassName();
try {
UIManager.setLookAndFeel(nome_classe_plaf);
SwingUtilities.updateComponentTreeUI(panel);
} catch (Exception ex) {
System.out.println("Errore nell'installazione del L&F");
}
}
});
setSize(200, 80);
}
/** Ridefiniamo setVisible per visualizzare il frame al centro. */
public void setVisible(boolean visible) {
Dimension dim_schermo = Toolkit.getDefaultToolkit().getScreenSize();
int pos_x = (dim_schermo.width - getSize().width) / 2;
int pos_y = (dim_schermo.height - getSize().height) / 2;
setLocation(pos_x, pos_y);
super.setVisible(visible);
}
public static void main(String str[]) {
PlafJFrame jframe = new PlafJFrame();
jframe.setVisible(true);
}
}
Il package della nostra applicazione è corso.swing.capitolo3, quello che raggruppa le classi relative al presente capitolo. Di seguito abbiamo importato le classi che utilizzeremo nell'applicazione, opportunamente elencate e divise per evidenziarle maggiormente.
Il primo gruppo riguarda le classi del package javax.swing. Il primo termine, javax, indica che le Swing sono considerate un'estensione delle Java core. Questo perché non sono necessarie alla creazione di un'interfaccia grafica, che si realizza anche con le sole AWT. Notiamo che le classi relative ai widget (JFrame, JComboBox e JPanel) hanno un nome caratterizzato dalla J iniziale. Notiamo inoltre la presenza dell'UIManager, descritto nel capitolo precedente, e della classe SwingUtilities, che raggruppa un insieme di funzioni di utilità nella gestione delle Swing.
Il secondo gruppo di import è relativo ad alcune classi di utilità del package java.awt. Di maggiore importanza è il terzo gruppo, che si riferisce alle classi e interfacce utilizzate nella gestione degli eventi. L'evento che gestiremo sarà quello relativo a una Action per cui, seguendo la regola dei nomi, l'oggetto relativo all'evento stesso si chiamerà java.awt.event.ActionEvent e l'interfaccia degli ascoltatori java.awt.event.ActionListener. Il package java.awt.event raggruppa infatti le classi e interfacce relative ai vari eventi.
La nostra classe PlafJFrame estende un JFrame, che esamineremo meglio, come gli altri widget di questa semplice applicazione, nei capitoli seguenti. Il costruttore contiene la maggior parte del codice.
Mettiamo in un array l'insieme delle descrizioni relative ai L&F disponibili. Attraverso il metodo statico getInstalledLookAndFeels() della classe UIManager si ottiene infatti un array di oggetti di tipo UIManager.LookAndFeelInfo che contengono le informazioni volute. Questo array ci sarà utile all'interno di una classe anonima, per cui lo indichiamo come final; la cosa non disturba, visto che il suo valore non cambia.
Mettiamo poi i nomi dei L&F disponibili in un array che utilizziamo per riempire un JComboBox. Consultando la documentazione di JComboBox, ci accorgiamo che essa è sorgente di un evento Action che notifica i suoi ascoltatori a ogni scelta. Creiamo allora un ascoltatore della combo attraverso una classe anonima. Essa dovrà semplicemente implementare il metodo actionPerformed() previsto dall'interfaccia ActionListener.
Prendiamo quindi l'indice del nuovo elemento selezionato e, utilizzando il precedente array delle informazioni relative ai vari L&F, il nome della classe corrispondente. Infine abilitiamo il nuovo L&F attraverso il metodo statico setLookAndFeel() della classe UIManager.
Questo non basta per modificare l'aspetto della nostra piccola applicazione. Per notificare a tutti i widget che devono aggiornare il loro Look si utilizza il metodo statico updateComponentTreeUI() della classe SwingUtilities. Per completezza facciamo una piccola nota relativa al metodo setVisible(), ridefinito per posizionare il JFrame al centro dello schermo.
Conclusioni
In questo impegnativo capitolo abbiamo approfondito gli aspetti di Java che più si utilizzano nella realizzazione di interfacce grafiche con le Swing. Abbiamo esaminato nel dettaglio i vari tipi di inner class e visto come si programma utilizzando una gestione degli eventi per delega, il Delegation Model. Abbiamo concluso con una piccola applicazione che mette in pratica gli aspetti relativi alla gestione del Pluggable LookAndFeel (PLAF).
