MokaByte 47 - Dicembre 2000

di
Andrea Gini
Corso di Swing
IV parte: i controlli
(parte prima)
Dopo aver trattato alcuni indispensabili argomenti teorici, iniziamo ora lo studio dei controlli grafici e dei relativi ascoltatori. In questo articolo affronteremo lo studio dei pulsanti, i componenti piu' usati; assieme ai controlli verranno introdotti alcuni esempi che illustrano una tipica situazione di utilizzo. 

Bottoni
I pulsanti, grazie alla loro modalita' di utilizzo estremamente intuitiva, sono sicuramenti i controlli grafici piu' usati. Swing offre quattro tipi di pulsanti, legati tra loro dalla gerarchia illustrata in Figura 1.
 
 
Figura 1 - Gerarchia dei bottoni Swing

JButton e' l'implementazione del comune bottone "Push"; JToggleButton e' un pulsante On-Off; JCheckBox e' un controllo grafico creato sul modello delle caselle di spunta dei questionari; JRadioButton e' un controllo che permette di scegliere una tra molte possibilita' in modo mututamente esclusivo. 
 
 

 Figura 2 - Pulsanti disponibili su Swing

La classe AbstractButton definisce l'interfaccia di programmazione comune a tutti i pulsanti: per questa ragione cominceremo il nostro studio da questa classe; dopo aver appreso il funzionamento di una delle sottoclassi concrete di AbstractButton, sara' abbastanza facile capire gli altri.
 
 
 

AbstractButton - Gestione dell'aspetto
L'API di AbstractButton definisce un insieme di metodi per gestire l'aspetto del componente; in particolare viene fornita la possibilita' di associare ad ogni controllo grafico un'ettichetta di testo, un'icona o entrambi. E' possibile impostare l'etichetta in formato HTML: basta aggiungere il prefisso "<html>" nel parametro di setText(String). Le seguenti righe di codice creeranno un JButton con un'ettichetta HTML:

JButton b =new JButton();
b.setText("<html><font size=-1><b><u>Esempio</u></b> di pulsante <b>HTML</b></font></html>")); 
 
 

Figura 3 - E' possibile decorare un pulsante con HTML

I pulsanti Swing permettono di impostare un'icona diversa per ognuno degli stati in cui si possono trovare: normale, premuto, selezionato (valido per i controlli che mantengono lo stato come i CheckBox), disabilitato e rollover (lo stato in cui si trova un controllo quando viene sorvolato dal puntatore del mouse).
 

  • void setText(String text): Imposta l'eticchetta di testo.
  • void setEnabled(boolean b): Abilita o disabilita il controllo.
  • void setRolloverEnabled(boolean b): Attiva o disattiva l'effetto rollover.
  • void setSelected(boolean b): Regola lo stato del controllo.
  • void setIcon(Icon defaultIcon): Imposta l'icona di default.
  • void setPressedIcon(Icon pressedIcon): Imposta l'icona per lo stato "premuto".
  • void setSelectedIcon(Icon selectedIcon): Imposta l'icona "selezionato".
  • void setDisabledIcon(Icon disabledIcon): Imposta l'icona "disabilitato". 
  • void setRolloverIcon(Icon rolloverIcon): Imposta l'icona "rollover".
  • void setDisabledSelectedIcon(Icon disabledSelectedIcon): Imposta l'icona per la combinazione "disabilitato - selezionato" 
  • void setRolloverSelectedIcon(Icon rolloverSelectedIcon): Imposta l'icona  per la combinazione "rollover selezionato"
Come icona possiamo usare un oggetto di tipo ImageIcon, ricorrendo al costruttore ImageIcon(String filename) che crea un'icona a partire da un'immagine di tipo GIF o JPEG il cui percorso viene specificato nella stringa del parametro. 
Il piu' delle volte e' sufficiente specificare l'icona di default, dal momento che le immagini per gli stati "premuto", "selezionato" e "disabilitato" vengono create in modo automatico a partire da quella principale. Le seguenti righe creano un pulsante decorato con l'immagine "img.gif" (puo' andar bene una qualunque immagine): ovviamente il file deve essere presente nella directory di lavoro,  altrimenti verra' creato un pulsante vuoto. 

  // crea un pulsante
  JButton b = new JButton();
  // crea un'icona
  ImageIcon icon = new ImageIcon("img.gif"); 
  // imposta icon come icona per b
  b.setIcon(icon); 
 

AbstractButton - Gestione degli eventi
I controlli derivati da AbstractButton prevedono due tipi di ascoltatore: ActionListener ed ItemListener. Il primo ascolta il tipo piu' semplice di evento, come la pressione di un pulsante; il secondo permette di conoscere i cambiamenti da "selezionato" a "non selezionato" o viceversa nei pulsanti tipo JToggleButton. Nei paragrafi seguenti vedremo alcuni esempi di utilizzo; qui di seguito possiamo vedere i metodi necessari ad aggiungere o rimuovere i gli  ascoltatori da un pulsante.
 
 

Figura 4 - Ascoltatori ed eventi per i pulsanti

 
  • void addActionListener(ActionListener l): aggiunge un ActionListener al pulsante
  • void removeActionListener(ActionListener l): rimuove un ActionListener dal pulsante
  • void addItemListener(ItemListener l): aggiunge un ItemListener al pulsante.
  • void removeItemListener(ItemListener l): rimuove un ItemListener dal pulsante.


E' da segnalare la possibilita' di attivare le azioni associate ad un pulsante in maniera equivalente a quella che si otterrebbe con un click del mouse. 

  • void doClick()  Esegue un click sul pulsante 
JButton
Vediamo ora la prima sottoclasse concreta di AbstractButton: JButton, il comune pulsante push. I seguenti costruttori permettono di creare pulsanti  e di definirne le principali proprieta'.
 
  • JButton(String text): Crea un pulsante con l'etichetta specificata dal parametro.
  • Button(Icon icon): Crea un pulsante con l'icona specificata dal parametro.
  • Button(String text, Icon icon): Crea un pulsante con l'etichetta e l'icona specificate dai parametri


Ogni Top Level container puo' segnalare un pulsante come DefaultButton. Esso verra' evidenziato in maniera particolare e verra' richiamato con la semplice pressione del tasto "Invio". Le righe seguenti creano un pulsante, un JFrame e impostano il pulsante come DefaultButton :

  JFrame f = new JFrame();
  JButton b = new JButton("DefaultButton");
  f.getContentPane().add(b);
  f.getRootPane().setDefaultButton(b); 

L'ascoltatore piu' utile per un JButton e' ActionListener, che riceve eventi di tipo ActionEvent quando il pulsante viene premuto e rilasciato. Di seguito ecco i metodi piu' importanti di ActionEvent

  • String getActionCommand(): restituisce una stringa che identifica il comando (se non viene specificata altrimenti, e' uguale all'etichetta del pulsante). 
  • String paramString(): restituisce un parametro che identifica l'evento.

 
Figura 5 - Relazione tra JButton e ActionEvent

Vediamo ora un programma di esempio che illustra l'uso di due JButton, uno dei quali viene registrato come DefaultButton, e dei relativi ascoltatori.
 
 

Figura 6 - Esempio di uso di JButton

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

public class JButtonExample extends JFrame {
  private JDialog dialog;
  private JButton okButton;
  private JButton jDialogButton;

  public JButtonExample() {
    // Imposta le proprieta' del Top Level Container
    super("JButtonExample");
    setBounds(10,35,200,70);
    getContentPane().setLayout(new FlowLayout(FlowLayout.CENTER));

    // Crea una finestra di dialogo modale, inizialmente invisibile
    dialog = new JDialog(this,"JDialog",true);
    dialog.setBounds(250,20,300,100);
    dialog.getContentPane().setLayout(new BorderLayout());
    dialog.getContentPane().add(BorderLayout.CENTER,new JLabel("Chiudi questa finestra per continuare",JLabel.CENTER));
    dialog.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);

    // Crea due pulsanti
    okButton = new JButton("OK");
    jDialogButton = new JButton("Open Frame");
    // Crea gli ascoltatori
    ActionListener okListener = new OKButtonListener();
    ActionListener openActionListener = new JDialogButtonListener();
    // Registra gli ascoltatori presso i pulsanti
    okButton.addActionListener(okListener);
    jDialogButton.addActionListener(openActionListener);

    //imposta okButton come DefaultButton
    getRootPane().setDefaultButton(okButton);

    // Aggiunge i pulsanti al Top Level Container
    getContentPane().add(okButton);
    getContentPane().add(jDialogButton);

    setVisible(true); 
  }
  // Ascoltatore del pulsante OK
  class OKButtonListener implements ActionListener {
      public void actionPerformed(ActionEvent e) {
        try {
          System.exit(0);
        }
        catch (Exception ex) {}
      }
    }
  // Ascoltatore del pulsante jDialog
  class JDialogButtonListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      dialog.setVisible(true);
    }
  }
 public static void main(String argv[])
 {
    JButtonExample b = new JButtonExample();
 }

 
 

JToggleButton
E un pulsante che puo' avere due stati: premuto e rilasciato. Clickando con il mouse si provoca il passaggio tra uno stato e l'altro. Alcuni costruttori permettono di creare JToggleButton e di impostarne le proprieta'.

  • JToggleButton(String text, Icon icon, boolean selected): Crea un pulsante con l'etichetta, l'icona e lo stato specificate dai parametri
  • JToggleButton(String text, boolean selected): Crea un pulsante con l'etichetta e lo stato specificate dai parametri
  • JToggleButton(Icon icon, boolean selected): Crea un pulsante conl'icona e lo stato specificate dai parametri, senza etichetta.
Un JToggleButton, quando viene premuto, genera un ActionEvent e un ItemEvent. L'evento piu' interessante per questo tipo di pulsanti  e' il secondo, che segnala il cambiamento di stato, cioe' il passaggio da premuto a rilasciato e viceversa. 
  • Object getItem(): restituisce l'oggetto che ha generato l'evento.
  • int getStateChange(): restituisce un intero che puo' assumere i valori ItemEvent.SELECTED o ItemEvent.DESELECTED 
  • String paramString(): restituisce un parametro che identifica l'evento.

 
Figura 7 - Relazione tra ItemEvent e JToggleButton

 

E' possibile comunque utilizzare ActionListener alla stessa maniera dell'esempio precedente: in questo caso verra' inviato un ActionEvent ad ogni click, indipendentemente dallo stato del pulsante. Il seguente esempio crea una finestra con un JToggleButton che permette di aprire e di chiudere una finestra di dialogo non modale.
 
 

 Figura 8 - Esempio di JToggleButton

 

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

public class JToggleButtonExample extends JFrame {

  private JDialog dialog;
  private JToggleButton jDialogButton;

  public JToggleButtonExample() {
    // Imposta le proprieta' del Top Level Container
    super("JToggleButtonExample");
    setBounds(10,35,250,70);
    FlowLayout fl=new FlowLayout(FlowLayout.CENTER)
    getContentPane().setLayout(fl);

    // Crea una finestra di dialogo non modale,
    //inizialmente invisibile
    dialog = new JDialog(this,"JDialog",false);
    dialog.setBounds(250,20,300,100);
    dialog.getContentPane().setLayout(new BorderLayout());
    dialog.getContentPane().add(BorderLayout.CENTER,new 
                     JLabel("Finestra Aperta",JLabel.CENTER));
    dialog.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

    // Crea il pulsante e lo registra presso il suo ascoltatore
    jDialogButton = new JToggleButton("Open / Close Frame",false);
    jDialogButton.addItemListener(new 
                          JDialogButtonItemListener());

    // Aggiunge il pulsante al Top Level Container
    getContentPane().add(jDialogButton);
    setVisible(true); 
  }
  // Ascoltatore di JDialogButton
  class JDialogButtonItemListener implements ItemListener {
    public void itemStateChanged(ItemEvent e) {
      int status = e.getStateChange();
      if(status == ItemEvent.SELECTED)
        dialog.setVisible(true);
      else
        dialog.setVisible(false);
    }
  }

 public static void main(String argv[]) {
    JToggleButtonExample b = new JToggleButtonExample();
 }

Il codice dell'ascoltatore JDialogButtonItemListener e' un po' piu' complesso di quello degli ActionListener dell'esempio precedente: il codice di questo tipo di ascoltatori deve normalmente prevedere una verifica dello stato in cui si trova trova il pulsante, al fine di scatenare la giusta reazione. La verifica dello stato viene effettuata interrogando l'oggetto ItemEvent con il metodo getStateChange().
 
 
 

JCheckBox
JCheckBox e' una sottoclasse di JToggleButton che ha una forma simile alle caselle di spunta dei questionari. Il suo funzionamento e' analogo a quello della superclasse, ma di fatto tende ad essere utilizzato in contesti in cui si offre all'utente la possibilita' di scegliere una o piu' opzioni tra un insieme, come avviene ad esempio nei pannelli di controllo. I costruttori disponibili sono gli stessi di JToggleButton, e cosi' pure la gestione degli eventi, pertanto non sara' necessario ripeterli. Un esempio mostrera' un uso tipico di questo componente.
 
 

Figura 9 - Con i due JCheckBox e' possibile due finestre di dialogo

 

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

public class JCheckBoxExample extends JFrame {

  private JDialog dialog1;
  private JDialog dialog2;
  private JCheckBox checkBox1;
  private JCheckBox checkBox2;

  public JCheckBoxExample() {
    // Imposta le proprieta' del Top Level Container
    super("JCheckBoxExample");
    setBounds(10,35,200,70);
    FlowLayout fl=new FlowLayout(FlowLayout.CENTER)
    getContentPane().setLayout(fl);

    // Crea due finestre di dialogo non modali, 
    // inizialmente invisibili
    dialog1 = new JDialog(this,"JDialog 1",false);
    dialog1.setBounds(250,20,300,100);
    dialog1.getContentPane().setLayout(new BorderLayout());
    dialog1.getContentPane().add(BorderLayout.CENTER,new 
               JLabel("Finestra 1 Aperta",JLabel.CENTER));
    dialog1.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
    dialog2 = new JDialog(this,"JDialog 2",false);
    dialog2.setBounds(250,150,300,100);
    dialog2.getContentPane().setLayout(new BorderLayout());
    dialog2.getContentPane().add(BorderLayout.CENTER,
      new JLabel("Finestra 2 Aperta",JLabel.CENTER));
    dialog2.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

    // Crea i checkBox e li registra presso il loro ascoltatore
    ItemListener listener = new JCheckBoxItemListener();
    checkBox1 = new JCheckBox("Finestra 1");
    checkBox1.addItemListener(listener);
    checkBox2 = new JCheckBox("Finestra 2");
    checkBox2.addItemListener(listener);

    // Aggiunge i checkBox al Top Level Container
    getContentPane().add(checkBox1);
    getContentPane().add(checkBox2);
    setVisible(true); 
  }
  // ascoltatore JCheckBox
  class JCheckBoxItemListener implements ItemListener {
    public void itemStateChanged(ItemEvent e) {
      Object target = e.getItem();
      int status = e.getStateChange();

      if(target.equals(checkBox1) 
          && status == ItemEvent.SELECTED)
        dialog1.setVisible(true);
      else if(target.equals(checkBox1)
          && status == ItemEvent.DESELECTED)
        dialog1.setVisible(false);
      else if(target.equals(checkBox2)
          && status == ItemEvent.SELECTED)
        dialog2.setVisible(true);
      else if(target.equals(checkBox2)
          && status == ItemEvent.DESELECTED)
        dialog2.setVisible(false);
    }
  }
 public static void main(String argv[]) {
    JCheckBoxExample b = new JCheckBoxExample();
 }

L'ascoltatore JCheckBoxItemListener presenta un grado di complessita' maggiore del precedente: esso ascolta entrambi i controlli, e ad ogni chiamata verifica quale dei due abbia generato l'evento (chiamando il metodo getItem() di ItemEvent) e quale stato ha assunto, e quindi predispone la reazione opportuna.
 
 
 

JRadioButton
JRadioButton e' una sottoclasse di JToggleButton, dotata dei medesimi costruttori. Questo tipo di controlli viene usato tipicamente per fornire all'utente la possibilita' di operare una scelta tra un insieme di possibilita', laddove una scelta esclude l'altra. Per implementare questo comportamento di mutua esclusione e' necessario registrare i JRadioButton che costituiscono l'insieme presso un'istanza della classe ButtonGroup, come viene mostrato nelle righe seguenti

  ButtonGroup group = new ButtonGroup();
  group.add(radioButton1);
  group.add(radioButton2);
  group.add(radioButton3);

Ogni volta che l'utente attiva uno dei pulsanti registrati presso il ButtonGroup, gli altri vengono automaticamente messi a riposo. Questo comportamento ha una conseguenza importante nella gestione degli eventi: un gruppo di JRadioButton registrati presso un ButtonGroup genera due ItemEvent consecutivi per ogni click del mouse, uno per la casella che viene selezionata ed uno per quella deselezionata. Di norma si e' interessati unicamente al fatto che un particolare JRadioButton sia stato premuto, poiche' la politica di mutua esclusione rende superfluo verificarne lo stato: in questi casi e' consigliabile utilizzare un ActionListener come nell'esempio seguente, nel quale un gruppo di  JRadioButton permette di modificare la scritta su un'etichetta di testo. 
 
 

Figura 10 - Attivando un JRadioButton l'etichetta viene modificata

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

public class JRadiobuttonExample extends JFrame {

  private JRadioButton radioButton1;
  private JRadioButton radioButton2;
  private JRadioButton radioButton3;
  private JLabel label;

  public JRadiobuttonExample() {
    // Imposta le proprieta' del Top Level Container
    super("JRadiobuttonExample");
    setBounds(10,35,150,150);
    getContentPane().setLayout(new FlowLayout(FlowLayout.CENTER));

    // Crea i radiobutton e la label
    radioButton1 = new JRadioButton("RadioButton 1");
    radioButton2 = new JRadioButton("RadioButton 2");
    radioButton3 = new JRadioButton("RadioButton 3");
    label = new JLabel();

    // Crea l'ascoltatore e registra i JRadioButton
    ActionListener listener = new JRadioButtonListener();
    radioButton1.addActionListener(listener);
    radioButton2.addActionListener(listener);
    radioButton3.addActionListener(listener);

    // Crea il ButtonGroup e registra i RadioButton
    ButtonGroup group = new ButtonGroup();
    group.add(radioButton1);
    group.add(radioButton2);
    group.add(radioButton3);

    // Aggiunge i componenti al Top Level Container
    getContentPane().add(radioButton1);
    getContentPane().add(radioButton2);
    getContentPane().add(radioButton3);
    getContentPane().add(label);

    radioButton1.doClick();
    setVisible(true); 
  }
  // Ascoltatore JRadioButton
  class JRadioButtonListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      String target = e.getActionCommand();
      label.setText(target);
    }
  }
 public static void main(String argv[]) {

    JRadiobuttonExample b = new JRadiobuttonExample();
 }

 
 
 

Conclusioni
In questo articolo abbiamo imparato l'uso dei pulsanti, grazie ad alcuni esempi che potete trovare in allegato nel file esempi.zip
Nel prossimo articolo impareremo dapprima a disporre i pulsanti all'interno di Tool Bar, quindi a realizzare menu a tendina.
 

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


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