MokaByte 49 - Febbraio 2001
Foto dell'autore non disponibile
di
Andrea Gini
Corso di Swing
VI parte: i controlli (JTextField)
Fino ad ora ci siamo coccupati di controlli dotati di una modalita' di interazione molto semplice, come i pulsanti. Ora affronteremo lo studio di componenti che permettono un'interazione con l'utente piu' complessa, utili in tutte le occasioni in cui e' necessario fornire la possibilita' di inserire valori arbitrari o di scegliere un elemento da una lista. 

I JTextField sono oggetti grafici che permettono di editare una singola riga di testo. Premendo il tasto "Invio" viene generato un ActionEvent, per segnalare agli ascoltatori che il testo e' stato immesso. Possiamo creare un JTextField usando i seguenti costruttori
  • JTextField(): Crea un TextField vuoto.
  • JTextField(int columns): Crea un TextField vuoto con il numero di colonne specificato dal parametro
  • JTextField(String text): Crea un TextField con il testo specificato dal parametro
  • JTextField(String text, int columns): Crea un JTextField con il testo e il numero di colonne specificati dai parametri.
I seguenti metodi permettono di impostare o di leggere le principali proprieta' dell'oggetto
  • setText(String text): permette di settare il contenuto del campo di testo.
  • String getText(): permette di leggere il contenuto del JTextField. 
  • setColumns(int columns): Imposta il numero di colonne. 
  • setFont(Font f): Imposta il Font.
  • setHorizontalAlignment(int alignment): regola l'allineamento del testo; il parametro puo assumere uno dei seguenti valori: JTextField.LEFT, JTextField.CENTER, JTextField.RIGHT


L'ascoltatore di default per JTextField e' ActionListener, che viene invocato alla pressione del tasto "Invio".  JTextField ha un metodo per impostare la stringa usata come command string per l'ActionEvent inviato. Se non viene specificto diversamente, tale stringa assume il valore del testo presente all'interno del componente.

  • addActionListener(ActionListener l): aggiunge un ActionListener al JTextField
  • setActionCommand(String command): imposta la "command string" gli l'ActionEvent.


Nell'esempio seguente vedremo come creare un  JTextField e un ascoltatore che reagisca all'inserimento di testo.
 
 


Figura 1 Un semplice campo di testo

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class JTextFieldExample extends JFrame {
  private JTextField textField; 
  private JLabel label;

  public JTextFieldExample() {
    super("JTextField");
    setSize(200,80);
    getContentPane().setLayout(new BorderLayout());

    textField = new JTextField();
    label = new JLabel();
    getContentPane().add(BorderLayout.NORTH,textField);
    textField.addActionListener(new EnterTextListener());
    getContentPane().add(BorderLayout.SOUTH,label);

    setVisible(true); 
  }
  class EnterTextListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      label.setText("Testo inserito: "+textField.getText());
      textField.setText("");
    }
  } 
 public static void main(String argv[])
 {
    JTextFieldExample jtf = new JTextFieldExample();
 }

 
 

JPasswordField
JPasswordField e' una sottoclasse di JTextField specializzata nell'inserimento di password. Le principali differenze rispetto alla superclasse sono due: la prima e' che su JPasswordField i caratteri digitati vengono visualizzati come asterischi; la seconda e' che il testo in chiaro viene restituito sotto forma di array di char invece che come stringa. Il metodo setEchoChar(char c) permette di impostare qualunque carattere al posto dell'asterisco di default; il metodo char[] getPassword() invece restituisce il contenuto del campo di testo in chiaro, sotto forma di array di char.
Il seguente esempio mostra la creazione di un JPasswordField e una tipica interazione con l'utente.


Figura 2 - JPasswordField impedisce di 
vedere il vero contenuto del campo di testo

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class JPasswordFieldExample extends JFrame {
  private JPasswordField passwordTextField; 
  private JLabel label;

  public JPasswordFieldExample() {
    super("JPasswordFieldExample");
    setSize(220,80);
    getContentPane().setLayout(new BorderLayout());

    passwordTextField = new JPasswordField();
    passwordTextField.setEchoChar('$');

    label = new JLabel();
    getContentPane().add(BorderLayout.NORTH,passwordTextField);
    passwordTextField.addActionListener(new EnterTextListener());
    getContentPane().add(BorderLayout.SOUTH,label);

    setVisible(true); 
  }
  private static boolean verifyPassword(char[] input) {
    char[] correctPassword = { 's', 'e', 'c', 'r', 'e', 't' };
    if (input.length != correctPassword.length)
      return false;
    for (int i = 0;  i < input.length; i ++)
      if (input[i] != correctPassword[i])
                return false;

      return true;
  }

  class EnterTextListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      if(verifyPassword(passwordTextField.getPassword()))
        label.setText("Password corretta");
      else
        label.setText("Password sbagliata");

      passwordTextField.setText("");
    }
  } 
 public static void main(String argv[]) {
    JPasswordFieldExample jpf = new JPasswordFieldExample();
 }

 
 
 

JComboBox
Attraverso i JComboBox e' possibile offrire all'utente la possibilita' di effettuare una scelta a partire da una lista di elementi, anche molto lunga. A riposo, il componente si presenta come un pulsante, con l'etichetta corrispondente al valore attualmente selezionato; un click del mouse provoca la comparsa di un menu provvisto di barra laterale di scorrimento, che mette in vista le opzioni disponibili. Se si imposta un JComboBox come editabile, esso si comportera' a riposo come un JTextField, permettendo all'utente di inserire valori non presenti nella lista.
E' possibile creare un JComboBox usando i seguenti costruttori; il secondo costruttore permette di inizializzare il componente con una lista di elementi di tipo String, Icon e JLabel

  • ComboBox(): crea un JComboBox vuoto
  • JComboBox(Object[] items): crea un JComboBox contenente gli elementi specificati dal parametro items.
Alcuni metodi permettono di manipolare gli elementi dalla lista:
  • void addItem(Object anObject): Aggiunge un elemento alla lista.
  • void removeItem(Object anObject): Rimuove un elemento dalla lista.
  • void removeItemAt(int anIndex): rimuove l'elemento nella posizione specificata dal parametro.
  • void removeAllItems(): rimuve tutti gli elementi.
  • Object getItemAt(int index): restituisce l'elemento contenuto nella posizione specificata.
  • int getItemCount(): restituisce il numero di elementi contenuto nella lista
  • void insertItemAt(Object anObject, int index): inserisce un elemento nella posizione specificata.


Per manipolare l'aspetto dell'oggetto si puo' ricorrere ai seguenti metodi

  • void setMaximumRowCount(int count): imposta il numero massimo di righe 
  • Object getSelectedItem(): restituisce l'elemento attualmente selezionato.
  • void setSelectedIndex(int anIndex): seleziona l'elemento all'indice specificato
  • void setSelectedItem(Object anObject): seleziona l'Object specificato nel parametro.
  • void setEnabled(boolean b): abilita-disabilita il componente.
  • void setEditable(boolean aFlag): imposta se il componente e' editabile oppure no.
Nel seguente esempio vengono creati due JComboBox: uno editabile e l'altro non editabile; nel primo e' possibile inserire gli elementi digitandoli direttamente dentro il componente e premendo invio. Come ascoltatori vengono usati due ActionListener: EditListener si occupa di  aggiungere alla lista i nuovi elementi, mentre SelectionListener viene invocato da entrambi i componenti al fine di aggiornare una JLabel con il valore dell'elemento selezionato.


Figura 3 - JComboBox permette di scegliere un
elemento da una lista







import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class JComboBoxExample extends JFrame {
  private JComboBox uneditableComboBox;
  private JLabel label;
  private JComboBox editableComboBox;
  private String[] items;

  public JComboBoxExample() {
    // Imposta le proprieta' del Top Level Container
   super("JComboBoxExample");
    setBounds(10,35,300,100);
    getContentPane().setLayout(new FlowLayout(FlowLayout.LEFT));

    // Crea 20 elementi
    items = new String[20];
    for(int i=0;i<20;i++)
      items[i]="Elemento numero "+String.valueOf(i);

    // Inizializza un ComboBox non editabile 
    uneditableComboBox= new JComboBox(items);
    ActionListener selectionListener = new SelectionListener();
    uneditableComboBox.addActionListener(selectionListener);

    label = new JLabel();

    // Inizializza un JComboBox editabile
    editableComboBox= new JComboBox();
    editableComboBox.setEditable(true);
    editableComboBox.addActionListener(new EditListener());
    editableComboBox.addActionListener(selectionListener);

    getContentPane().add(uneditableComboBox);
    getContentPane().add(editableComboBox);
    getContentPane().add(label);

    setVisible(true); 
  }

  class SelectionListener implements ActionListener {
      public void actionPerformed(ActionEvent e) {
        JComboBox cb = (JComboBox)e.getSource();
        String selectedItem = (String)cb.getSelectedItem();
        label.setText("Selezionato: "+selectedItem);
      }
    }
    class EditListener implements ActionListener {
      public void actionPerformed(ActionEvent e) {
        JComboBox cb = (JComboBox)e.getSource();
        String selectedItem = (String)cb.getSelectedItem();
        editableComboBox.addItem(selectedItem);
        editableComboBox.setSelectedItem("");
      }
    }
 public static void main(String argv[]) {
    JComboBoxExample b = new JComboBoxExample();
 }
}
 
 
 

JList
JList e' un altro componente che permette di scegliere tra elementi che compongono una lista; diversamente da JComboBox e' possibile selezionare piu' di un elemento per volta, utilizzando il tasto "SHIFT" per selezionare elementi contigui o il tasto "CTRL" per elementi separati.
Per utilizzare in modo completo JList e' necessario comprendere la sua struttura interna: come si puo' vedere dalla Figura 4, JList mantiene gli elementi della lista in un oggetto conforme all'interfaccia ListModel. Il package javax.swing contiene DefaultListModel, un'implementazione di JList di uso generico, che permette di aggiungere o togliere a piacere elementi dalla lista.


Figura 4 - Architettura di JList

Contrariamente a quanto suggerisce il nome, DefaultListModel non e' il modello di default: se creiamo una JList a partire da un vettore, esso utilizzera' un proprio ListModel non modificabile, al quale non potranno essere aggiunti o tolti elementi. Se vogliamo creare una JList piu' flessibile, dobbiamo procedere nel modo seguente

  listModel = new DefaultListModel();
  listModel.addElement("Elemento 1");
  listModel.addElement("Elemento 2");
  ....
  list = new JList(listModel); 

Per visualizzare correttamente JList e' indispensabile montarlo all'interno di un JScrollPane, un pannello dotato di scrollbar, e aggiungere quest'ultimo al pannello principale; in caso contrario non sara' possibile visualizzare tutti gli elementi presenti nella lista.

  list = new JList(listModel); 
  JScrollPane scroll = new JScrollPane(list);
  panel.add(scroll);

Ecco i costruttori e i metodi piu' importanti

  • JList(ListModel dataModel): crea una JList, che mantiene gli elementi nel modello specificato.
  • JList(Object[] listData): crea una JList a partire dal vettore di elementi che costituiscono il parametro. La lista cosi' costituita non puo' essere modificata
  • void clearSelection(): azzera la selezione. 
  • int getSelectedIndex(): restituisce l'indice del primo elemento selezionato. Se al momento non e' selezionato alcun elemento, viene restituito -1 .
  • int[] getSelectedIndices(): restituisce in un array gli indici degli elementi selezionati in ordine crescente. 
  • Object getSelectedValue(): restituisce il primo elemento selezionato, o null se al momento non e' selezionato alcun elemento.
  • Object[] getSelectedValues(): restituisce in un vettore gli elementi selezionati.
  • boolean isSelectedIndex(int index): permette di sapere se l'elemento all'indice specificato e' selezionato o meno.
  • void setSelectedIndex(int index): seleziona l'elemento all'indice specificato.
  • void setSelectedIndices(int[] indices): seleziona un insieme di celle.
  • void setSelectionInterval(int anchor, int lead): seleziona un intervallo di celle.
  • void setSelectionMode(int selectionMode): imposta la modalita' di selezione. Il parametro puo' assumere i valori: JList.SINGLE_SELECTION se si desidera che si possa selezionare un solo elemento per volta; JList.SINGLE_INTERVAL_SELECTION se si vuole permettere la selezione di un singolo intervallo per volta; JList.MULTIPLE_INTERVAL_SELECTION se non si vuole porre restrizioni al numero di elementi o intervalli selezionabili.



Figura 5 - Modello degli eventi per JList 

Ogni volta che l'utente seleziona un elemento, viene notificato un ListeSelectionEvent ai ListeSelectionListener registrati. I metodi di ListeSelectionEvent permettono di conoscere gli indici di inizio e di fine della selezione. Attraverso il metodo boolean getValueIsAdjusting() e' possibile sapere se l'utente sta' ancora operando sulla selezione, o se ha terminato rilasciando il pulsante del mouse. 

  • void addListSelectionListener(ListSelectionListener listener): registra un ListSelectionListener, che verra' notificato ogni qual volta viene selezionato un elemento (o un gruppo di elementi) dalla JList.
  • void removeListSelectionListener(ListSelectionListener listener): rimuove l'ascoltatore specificato.


L'esempio seguente crea un JList con 20 elementi, selezionabili ad intervalli non contigui, e un'area di testo non modificabile che elenca gli elementi attualmente selezionati.


Figura 6 - Tenendo premuto il 
tasto CTRL è possibile selezionare 
elementi non contigui





import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;

public class JListExample extends JFrame {

  private JList list;
  private JTextArea output;

  public JListExample() {
    super("JListExample");
    setSize(170,220);
    getContentPane().setLayout(new GridLayout(0,1));

    // Crea 20 elementi
    String[] items = new String[20];
    for(int i=0;i<20;i++)
      items[i]="Elemento numero "+String.valueOf(i);

    // Inizializza una JList 
    list= new JList(items);
    list. setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    ListSelectionListener selectionListener = new SelectionListener();
    list.addListSelectionListener(selectionListener);

    // Crea la TextArea di output
    output = new JTextArea();
    output.setEditable(false);

    // assembla la GUI
    getContentPane().add(new JScrollPane(list));
    getContentPane().add(new JScrollPane(output));
    setVisible(true); 
  }
  class SelectionListener implements ListSelectionListener {
      public void valueChanged(ListSelectionEvent e) {
        if(!e.getValueIsAdjusting()) {
          JList list = (JList)e.getSource();
          output.setText("");
          Object[] selectedItems = list.getSelectedValues();
          for(int i=0;i<selectedItems.length;i++)
            output.append(selectedItems[i].toString()+"\n");
        }
      }
    }
 public static void main(String argv[])
 {

    JListExample b = new JListExample();
 }

 
 
 

JSlider
JSlider e' un cursore a slitta, che permette di inserire valori numerici compresi tra un massimo ed un minimo in maniera continua, eliminando di fatto la possibilita' di inserire valori non corretti. L'insieme di controlli AWT comprende un componente simile, Scrollbar; le caratteristiche presenti in JSlider sono tuttavia molto piu' avanzate, ed offrono maggiori possilita' di personalizzazione.

Le proprieta' piu' importanti di un JSlider sono il valore minimo, il valore massimo e l'orientamento, che puo' essere orizzontale o verticale; i costruttori permettono di specificare tutte queste proprieta' al momento della creazione dell'oggetto. Altre importanti proprieta' permettono di specificare il formato del righello graduato che decora lo slider e ne suggerisce l'uso. Le righe di codice seguenti chiariranno meglio l'uso di questo componente.

  slider = new JSlider(JSlider.HORIZONTAL,0,60,15);
    slider.setMajorTickSpacing(10);
    slider.setMinorTickSpacing(5);
    slider.setPaintTicks(true);
    slider.setPaintLabels(true);

Il costruttore crea un JSlider orizzontale, la cui scala varia tra 0 e 60 con il cursore posizionato sul 15; seguono due metodi che impostano la spaziatura tra le tacche del righello: il primo imposta la spaziatura tra le tacche piu' grandi, il secondo tra quelle piu' piccole. Gli ultimi due metodi attivano il disegno del righello e della guida numerata, normalmente disattivati.
Questi pochi metodi permettono di creare un gran numero di slider, come e' possibile vedere in Figura 7.


Figura 7 - Alcuni esempi di JSlider

Esiste la possibilita' di personalizzare ulteriormente l'aspetto del componente, specificando etichette non regolari. Per farlo bisogna chiamare il metodo setLabelTable(HashTable h), passando come parametro una HashTable contenente coppie chiave-valore composte da un oggetto di tipo Int e un Component: ogni Component verra' disegnato in corrispondenza della tacca specificata dell'intero passato come chiave. Nelle righe seguenti viene illustrato come creare un JSlider con etichette testuali; ovviamente e' possibile utilizzare al posto delle label qualunque tipo di componente, ad esempio JLabel contenenti icone, o addirittura pulsanti programmati per riposizionare il cursore su valori preimpostati.

  slider = new JSlider(JSlider.VERTICAL,0,70,15);
  slider.setMajorTickSpacing(10);
  slider.setPaintTicks(true);

  Hashtable labelTable = new Hashtable();
  labelTable.put( new Integer( 0 ), new JLabel("Silence") );
  labelTable.put( new Integer( 10 ), new JLabel("Low") );
  labelTable.put( new Integer( 30 ), new JLabel("Normal") );
  labelTable.put( new Integer( 70 ), new JLabel("Loud!") );
  slider.setLabelTable( labelTable );


Figura 8 - Con il metodo setLabelTable() 
è possibile personalizzare il righello

Ogni volta che si manipola un JSlider, viene generato un ChangeEvent. Un ascoltatore di tipo ChangeListener deve implementare il metodo stateChanged(ChangeEvent e), come si vede nell'esempio qui sotto. E' possibile conoscere lo stato di un JSlider attraverso due metodi: getValue() restituisce il valore intero su cui il cursore e' attualmente posizionato, getValueIsAdjusting() restituisce true se l'azione di modifica e' tuttora in corso. Un ascoltatore come il seguente effettua un'azione solamente quando il cursore viene rilasciato, e scarta tutti gli eventi di aggiustamento.

  class SliderChangeListener implements ChangeListener {
      public void stateChanged(ChangeEvent e) {
        JSlider slider = (JSlider)e.getSource();
        if(!slider.getValueIsAdjusting())
          label.setText("Selezionato: "
            +String.valueOf(slider.getValue()));
      }
  }
 

  • JSlider(int orientation, int min, int max, int value): crea un JSlider con l'orientamento specificato dal parametro orientation, che puo' assumere i due valori JSlider.VERTICAL o JSlider.HORIZONTAL. I parametri min e max specificano i valori limite della scala, mentre value indica la posizione iniziale del cursore.
  • void addChangeListener(ChangeListener l) : aggiunge un ChangeListener al componente.
  • void removeChangeListener(ChangeListener l) : rimuove il ChangeListener dalla lista degli ascoltatori
  • void setOrientation(int orientation): imposta l'orientamento dello slider; il parametro puo' assumere i valori JSlider.HORIZONTAL o JSlider.VERTICAL
  • void setValue(int value): imposta il cursore sul valore specificato dal parametro 
  • int getValue(): restituisce il valore corrente dello slider.
  • void setInverted(boolean b): se il parametro e' true, la scala viene disegnata da destra a sinistra (o dal basso all'alto) invece che il contrario.
  • void setMinimum(int min):  imposta il valore minimo della scala.
  • void setMaximum(int max): imposta il valore massimo della scala.
  • void setPaintTicks(boolean b): attiva o disattiva la visualizzazione del righello.
  • void setMajorTickSpacing(int):  imposta la spaziatura tra le tacche grandi del righello.
  • void setMinorTickSpacing(int): imposta la spaziatura tra le tacche piccole del righello.
  • void setPaintLabels(boolean b): attiva o disattiva la visualizzazione delle etichette.
  • void setLabelTable(HashTable Dictionary): imposta una HashTable contenente le informazioni per disegnare la tabella delle etichette.
  • Hashtable createStandardLabels(int increment): crea una HashTable che disegni etichette con l'incremento specificato dal parametro.


I sorgenti completi possono essere scaricati 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