venerdì 25 giugno 2010

Java: componenti swing per le GUI

Una volta conosciuti i limiti e le caratteristiche di alcuni layout possiamo adesso dare uno sguardo ai componenti Swing per le GUI. Vi presenterò i componenti più usati. Trovate, come sempre, un elenco assai più lungo nella documentazione in linea messa a disposizione da SUN Microsystems.

Campi di testo
Per l'immissione del testo esistono essenzialmente due componenti Swing: JTestField e JTextArea. Si tratta di due classi che estendono la classe (astratta) JTextComponent ereditando, quindi, dalla stessa alcuni metodi come:
  • setText(): che riceve una stringa, come parametro, da aggiunge al componente;
  • getText(): che ritorna il testo inserito dall'utente nel componente;
  • setEditable(): che riceve un valore booleano come parametro affinchè si possa abilitare/disabilitare in scrittura il componente;
Ecco subito un esempio:

JTextField area1=new JTextField("Inserire un valore",15);

Esistono più versioni del costruttore JTextField, uno specifica con un numero intero il numero di colonne del componente, mentre un secondo costruttore (come quello usato nell'esempio) permette di specificare una stringa iniziale e il numero di colonne. Se il testo supera il numero di colonne previste quest'ultimo, allora, scorrerà sull'unica riga di input! Se invece vogliamo dare all'utente la possibilità di inserire un testo su più righe abbiamo allora bisogno di un'area di testo:

JTextArea area2=new JTextArea(5,15);

Dove i parametri passati indicano,rispettivamente, il numero di righe e il numero di colonne da assegnare al componente. Il solo uso di un componente JTextArea, ne sono sicuro, non soddisfa quasi mai ne l'utente ne il programmatore. Perchè? Se il testo eccede il numero di colonne il componente viene ridimensionato! Per fissare la sua dimensione e adagiare il testo al suo interno occorre aggiungere al componente un'utile barra di scorrimento con il seguente codice:

JTextArea area2=new JTextArea(5,15);
JScrollPane area2_con_barra=new JScrollPane(area2);


Esiste, infine, un secondo costruttore per il componente JTextArea che permettte di specificare una stringa iniziale da aggiungere al componente (vedere l'esempio successivo). Un metodo usato spesse volte con un componente JTextArea, per l'aggiunta di nuovo testo, è il metodo append. Attraverso questo metodo la strnga passata come parametro viene aggiunta in coda al testo già esistente nel componente!

public class Pannello_GUI extends JPanel {
   public Pannello_GUI() {
      this.setLayout(new BorderLayout());
      JPanel pannello_CENTER=new JPanel();
      JTextField area1=new JTextField("Inserire un valore",15);
      JTextArea area2=new JTextArea("Inserire una descrizione",5,15);
      JScrollPane area2_con_barra=new JScrollPane(area2);
      pannello_CENTER.add(area1);
      pannello_CENTER.add(area2_con_barra);
      this.add(pannello_NORTH,BorderLayout.CENTER);
   }
}


Un particolare componente JTextField è il componente JPasswordField che, come avrete sicuramente intuito, permette l'input di password o dati sensibili nascondendoli da sguardi indiscreti. Il costruttore permette di specificare una stringa iniziale e il numero di colonne da assegnare al componente. Ogni carattere lì digitato verrà sostituito da un carattere che farà da echo (solitamante un asterisco). Inoltre, se vogliamo modificare il carattere di echo possiamo invocare sul componente il metodo setEchoChar e passare a questo il nuovo carattere di echo! L'accesso al valore nascosto, invece, avviene con il metodo getPassword che ritorna un array di caratteri:

public class Pannello_GUI extends JPanel {
   public Pannello_GUI() {
      this.setLayout(new BorderLayout());
      JPanel pannello_NORTH=new JPanel();
      JPasswordField area1=new JPasswordField("",15);
      area1.setEchoChar('*');
      pannello_NORTH.add(area1);
      this.add(pannello_NORTH,BorderLayout.CENTER);
   }
}

Label o etichette per i componenti
Finora ogni componente aggiunto al pannello dell'interfaccia grafica era privo di un riferimento utile a far capire all'utente cosa effettivamente scrivere nei campi dati. Per suggerire all'utente l'utilità di un campo dati si ricorre al componente JLabel:

public class Pannello_GUI extends JPanel {
   public Pannello_GUI() {
      this.setLayout(new BorderLayout());
      JLabel etichetta1=new JLabel("Password:");
      JPanel pannello_CENTER=new JPanel();
      JPasswordField area1=new JPasswordField("",10);
      area1.setEchoChar('*');
      pannello_CENTER.add(etichetta1);
      pannello_CENTER.add(area1);
      this.add(pannello_NORTH,BorderLayout.CENTER);
   }
}

Attenzione all'ordine con cui inserite i componenti!


Caselle per la scelta di opzioni
L'interfaccia Java, così avviene per i form html, offre all'utente la possibilità di effettuare una scelta di un input attraverso l'uso di caselle o checkbox. Una checkbox può avere un proprio significato, essere cioè indipendente da altre checkbox, oppure può appartenere a un gruppo di checkbox (in cui la selezione di una disabilita tutte le altre). A differenza dei precedenti componenti, le checkbox prevedono all'interno del costruttore una label da passare allo stesso componente (sotto forma di stringa). Ecco un esempio:

JCheckBox protocollo=new JCheckBox("Protocollo sicuro");

Per stabilire lo stato del componente si può chiamare su di esso il metodo isSelected (che ritorna true se il componente è selezionato, false se deselezionato). Se invece bisogna selezionare di default una checkbox si deve allora chiamare su di essa il metodo setSelected e passare, quindi, un valore booleano. Per un gruppo di checkbox va invece usato il componente ButtonGroup che permette di istanziare un componente in grado di integrare (attraverso il metodo add), sotto un unico gruppo, più checkbox (create questa volta attraverso JRadioButton):

ButtonGroup server=new ButtonGroup();
JRadioButton server1=new JRadioButton("Server Nro 1",true);
JRadioButton server2=new JRadioButton("Server Nro 2",false);
server.add(server1);
server.add(server2);

Al costruttore di JRadioButton occorre passare una label e un valore booleano. Attenzione, uno solo dei valori appartenenti al componente ButtonGroup dovrà avere il valore true!

public class Pannello_GUI extends JPanel {
   public Pannello_GUI() {
      this.setLayout(new BorderLayout());
      JLabel etichetta1=new JLabel("Password:");
      JPanel pannello_NORTH=new JPanel();
      JPasswordField area1=new JPasswordField("",10);
      area1.setEchoChar('*');
      pannello_NORTH.add(etichetta1);
      pannello_NORTH.add(area1);
      JPanel pannello_CENTER=new JPanel();
      JCheckBox protocollo=new JCheckBox("Protocollo sicuro");
      pannello_CENTER.add(protocollo);
      JPanel pannello_SOUTH=new JPanel();
      ButtonGroup server=new ButtonGroup();
      JRadioButton server1=new JRadioButton("Server Nro 1",true);
      JRadioButton server2=new JRadioButton("Server Nro 2",false);
      server.add(server1);
      server.add(server2);
      pannello_SOUTH.add(server1);
      pannello_SOUTH.add(server2);
      this.add(pannello_NORTH,BorderLayout.NORTH);
      this.add(pannello_CENTER,BorderLayout.CENTER);
      this.add(pannello_SOUTH,BorderLayout.SOUTH);
   }
}


Combo box
Con il componente JComboBox possiamo inserire in un pannello un menu attraverso cui selezionare un valore:

JComboBox server=new JComboBox();
server.addItem("Server N.ro 1");
server.addItem("Server N.ro 2");
server.addItem("Server N.ro 3");

Il metodo AddItem permette l'aggiunta di nuove voci all'interno del componente. L'elemento selezionato viene quindi recuperato attraverso la chiamata al metodo getSelectedItem. Se si vuole dare la possibilità di modificare una voce all'interno della lista (anche a runtime) occorre abilitare in scrittura il componente mediante il metodo setEditable (che accetta come parametro un valore booleano).

public class Pannello_GUI extends JPanel {
   public Pannello_GUI() {
      this.setLayout(new BorderLayout());
      JLabel etichetta1=new JLabel("Password:");
      JPanel pannello_NORTH=new JPanel();
      JPasswordField area1=new JPasswordField("",10);
      area1.setEchoChar('*');
      pannello_NORTH.add(etichetta1);
      pannello_NORTH.add(area1);
      JPanel pannello_CENTER=new JPanel();
      JCheckBox protocollo=new JCheckBox("Protocollo sicuro");
      pannello_CENTER.add(protocollo);
      JPanel pannello_SOUTH=new JPanel();
      JLabel etichetta2=new JLabel("Server:");
      JComboBox server=new JComboBox();
      server.setEditable(true);
      server.addItem("Server N.ro 1");
      server.addItem("Server N.ro 2");
      server.addItem("Server N.ro 3");
      pannello_SOUTH.add(etichetta2);
      pannello_SOUTH.add(server);
      this.add(pannello_NORTH,BorderLayout.NORTH);
      this.add(pannello_CENTER,BorderLayout.CENTER);
      this.add(pannello_SOUTH,BorderLayout.SOUTH);
   }
}


Menu
I menu a discesa caratterizzano da sempre gli ambienti e i programmi organizzati in frame. Si tratta di un componente indispensabile per alcune applicazioni, soprattutto quando non si vuole riempire eccessivamente il pannello utente. Ecco allora che conviene organizzare all'interno di un menu a discesa ogni comando che è possibile inviare al programma in esecuzione. La barra contenente un menu raggruppa sotto alcune voci principali i comandi e/o le funzionalità del programma e può, quindi, essere articolato in un o più sotto livelli di menu. La classica barra dei menu presente nei programmi Windows ne è un tipico esempio, lì solitamente troviamo una voce File, Edit, View etc... Per aggiungere una barra per il menu bisogna creare un oggetto JMenuBar:

JMenuBar menu=new JMenuBar();

che farà da contenitore a tutte le voci. Quindi bisogna aggiungere le voci principali aggiungendo in ognuna di queste una o più oggetti JMenuItem, attraverso il metodo add:

JMenu fileMenu=new JMenu("File");
JMenuItem apriFile=new JMenuItem("Apri file");
JMenuItem chiudiFile=new JMenuItem("Chiudi file");
JMenuItem esciFile=new JMenuItem("Esci");
fileMenu.add(apriFile);
fileMenu.add(chiudiFile);
fileMenu.add(esciFile);

Fatto ciò occorre aggiungere il singolo menu al contenitore dei menu, overro alla barra in alto dei menu con il comando:

menu.add(fileMenu);

Attenzione, la barra dei menu va aggiunta al frame che contiene i pannelli e non ai pannelli! Per questo motivo ho modificato leggermente la classe che descrive e dispone i componenti nel frame:

public class Pannello_GUI extends JPanel {
   public Pannello_GUI(Finestra finestra) {
      this.setLayout(new BorderLayout());
   JLabel etichetta1=new JLabel("Password:");
   JPanel pannello_NORTH=new JPanel();
   JPasswordField area1=new JPasswordField("",10);
   area1.setEchoChar('*');
   pannello_NORTH.add(etichetta1);
   pannello_NORTH.add(area1);
   JPanel pannello_CENTER=new JPanel();
   JCheckBox protocollo=new JCheckBox("Protocollo sicuro");
   pannello_CENTER.add(protocollo);
   JPanel pannello_SOUTH=new JPanel();
   JLabel etichetta2=new JLabel("Server:");
   JComboBox server=new JComboBox();
   server.setEditable(true);
   server.addItem("Server N.ro 1");
   server.addItem("Server N.ro 2");
   server.addItem("Server N.ro 3");
   pannello_SOUTH.add(etichetta2);
   pannello_SOUTH.add(server);
   JMenuBar menu=new JMenuBar();
   JMenu fileMenu=new JMenu("File");
   JMenuItem apriFile=new JMenuItem("Apri file");
   JMenuItem chiudiFile=new JMenuItem("Chiudi file");
   JMenuItem esciFile=new JMenuItem("Esci");
   fileMenu.add(apriFile);
   fileMenu.add(chiudiFile);
   fileMenu.add(esciFile);
   JMenu impostazioniMenu=new JMenu("Impostazioni");
   JMenuItem modificaImpostazioni=new JMenuItem("Modifica impostazioni");
   impostazioniMenu.add(modificaImpostazioni);
   JMenu infoMenu=new JMenu("Info");
   JMenuItem guidaInfo=new JMenuItem("Guida");
      infoMenu.add(guidaInfo);
      menu.add(fileMenu);
      menu.add(impostazioniMenu);
      menu.add(infoMenu);
   finestra.setJMenuBar(menu);
      this.add(pannello_NORTH,BorderLayout.NORTH);
   this.add(pannello_CENTER,BorderLayout.CENTER);
   this.add(pannello_SOUTH,BorderLayout.SOUTH);
   }
}


Termino qui questa breve presentazione di componenti per interfacce Java. Vorrei comunque ricordare, nuovamente, che i componenti fin qui visti non esauriscono l'intero set di componenti Swing. Per questo motivo invito gli utenti a cercare gli stessi, nonchè i metodi, all'interno della documentazione in linea (e nelle rispettive classi padre)!

Nessun commento:

Posta un commento