Paola Magillo, Univestita' di Genova, Corso di Interfacce Utente per Informatica, a.a. 2002-2003.

INTERFACCE GRAFICHE IN JAVA - IV

[Per corso su Java vedere http://java.sun.com/docs/books/tutorial/]

Dialoghi pronti all'uso

Una finestra di dialogo (classi Dialog / JDialog) quando viene creata e' vuoto.

In Swing esistono option panels, tipi di pannelli predefiniti che si possono mettere dentro un dialogo. Contengono:

Esempio

  1. JOptionPane option = new JOptionPane ("Hai capito?", JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_OPTION);
  2. JDialog dialog = option.createDialog(frame,"Una domanda...");
  3. dialog.pack();
  4. dialog.setVisible(true);
  5. int n = ((Integer)option.getValue()).intValue();

L'istruzione 1 crea un option panel cosi':

L'istruzione 2 crea dialogo che dipende funzionalmente da un frame ed ha come pannello di contenuto l'option panel appena creato. La stringa "Una domanda..." apparira' come titolo sul bordo (se il WM lo mettera').

Le istruzioni 3 e 4 dimensionano il dialogo e lo mostrano.

I due bottoni presenti nel pannello hanno automaticamente l'effetto di chiudere la finestra di dialogo, quando premuti. Chiuso il dialogo, il controllo passa all'istruzione successiva (5).

L'istruzione 5 legge il numero del bottone premuto per chiudere il dialogo.

Mostrare dialoghi

Classe JOptionPane ha metodi per mostrare dialoghi modali dipendenti funzionalmente da un frame:

Premere uno dei bottoni presenti sul dialogo ne provoca la chiusura.
Questi metodi ritornano il numero del bottone premuto per chiudere il dialogo.

Esistono anche dialoghi predefiniti che consentono immissione di una stringa.

Esempi

1) Esattamente lo stesso esempio visto prima:
int n = JOptionPane.showConfirmDialog
                (frame,
                 "Hai capito?",
                 "Una domanda...",
                 JOptionPane.YES_NO_OPTION,
                 JOptionPane.QUESTION_MESSAGE);
2)
JOptionPane.showMessageDialog(frame, "messaggio", "titolo",
                              JOptionPane.PLAIN_MESSAGE);

Object[] options = {"questa", "quella", "l'altra"};
int n = JOptionPane.showOptionDialog(frame, "Quale delle tre?", "titolo",
        JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE,
        new ImageIcon("icon.gif"), options, options[2]);

Come e' stato chiuso il dialogo

Esistono costanti per indicare il bottone premuto per chiudere il dialogo: JDialog.OK_OPTION, JDialog.YES_OPTION, JDialog.NO_OPTION, JDialog.CANCEL_OPTION.

Invece la costante JDialog.CLOSE_OPTION indica che il dialogo e' stato chiuso agendo sul bordo della finestra.

Altri contenitori

Pannelli a schedario

Permettono a piu' componenti (di solito pannelli) di condividere lo stesso spazio.
Ogni componente viene gestita come una scheda con linguetta sporgente. Selezionando la linguetta l'utente stabilisce quale scheda va mostrata davanti alle altre.

Creare uno schedario:

La posizione specifica su che lato saranno visualizzate le "linguette" delle varie schede (di default su quello superiore). Valori possibili: JTabbedPane.TOP, .BOTTOM, .LEFT, .RIGHT.

Per aggiungere componenti allo schedario non si usa "add" ma si usa un metodo apposito:

Il titolo e' la stringa da mostrare sulla linguetta. L'icona (se presente) viene anch'essa mostrata sulla linguetta.

La componente selezionata e' quella la cui scheda e' in questo momento davanti alle altre, e quindi quella che l'utente vede e con cui puo' interagire.

Per assegnare / ottenere la componente selezionata:

I metodi per gestire lo schedario (ordinamento, selezione, abilitazione / disabilitazione di schede) identificando le componenti tramite indici interi.

Toolbar

Barra orizzontale o verticale contenente componenti (in genere bottoni con etichette grafiche).

Puo' essere trascinata e posizionata a piacere su uno dei quattro lati della finestra che la ospita o fuori dalla sua finestra e il sistema automaticamente la colloca in finestra indipendente apposita.


Il contenitore deve usare BorderLayout. La toolbar deve stare in una delle quattro zone diverse da CENTER. La zona CENTER puo' ospitare (e di solito ospita) un'altra componente. Le altre tre zone devono essere vuote.

Costruire una toolbar:

toolbar = new JToolBar();
toolbar.add(new JButton("uno"));
toolbar.add(new JButton("due"));
toolbar.add(new JButton("tre"));
toolbar.addSeparator();
toolbar.add(new JButton("ultimo"));

La toolbar ha tre bottoni, uno spazio (separatore) e poi un'altro bottone.

I bottoni sono disposti in fila nell'ordine in cui li ho inseriti. Posso controllarne l'allineamento specificando setAlignmentX/Y per ciascun bottone che aggiungo.

Posso aggiungere qualsiasi tipo di componenti ad una toolbar, di solito sono bottoni.

Per stabilire se la toolbar puo' essere spostata trascinandola:

toolbar.setFloatable(true/false);

Altri dispositivi

Campi ed aree di testo

4 campi di testo:area di testo:

Campo di testo

Mostra una sola linea di testo editabile. Genera ActionEvent quando utente preme il tasto "return".

Creare un campo di testo:

TextField(String);
TextField(int);
TextField(String);
TextField(String,int);
La stringa e' il contenuto iniziale, l'intero e' la larghezza in numero di caratteri del campo.

Leggere e assegnare il testo contenuto:

void setText(String)
String getText()

Possibilita' di controllare la validita' secondo regole sintattiche del testo inserito.

In Swing, esiste sottoclasse JPasswordField di JTextField che funziona in modo identico ma la scritta inserita e' nascosta (al posto delle lettere sono mostrati caratteri di "echo").
In AWT e' possibile specificare che la stringa mostrata in un campo di testo non deve essere mostrata in chiaro.

Aree di testo

Area di testo su piu' linee, editabile dall'utente tramite tastiera e mouse.

In AWT puo' avere barre di scorrimento laterali. In Swing non sono previste, ma posso inserire l'area di testo dentro uno scrolled panel.

Costruzione di area di testo (vediamo AWT, Swing e' analogo):

tarea = new TextArea();
tarea = new TextArea(numerorighe,numerocolonne);
tarea = new TextArea(testoiniziale);
tarea = new TextArea(testoiniziale,numerorighe,numerocolonne);

Metodi utili per area di testo:

Esempio:

JTextArea textArea = new JTextArea("Questo e' un esempio ");
textArea.setFont(new Font("Serif", Font.ITALIC, 16));
Ritorno a capo (solo in Swing):

Per default, l'area di testo non va a capo, ma mostra tutto su linea unica e, se inserita in scroll pane, permette di scorrere orizzontalmente.

Combo box

Una combo box puo' essere non editabile o editabile (di default non editabile).

Combo box non editabile si presenta come un bottone fino a che l'utente non interagisce con essa. Quando l'utente interagisce, appare una tendina con lista di scelte come in un menu'.

Combo box editabile appare come un campo di testo con un piccolo bottone accanto. L'utente puo' digitare nel campo di testo oppure agire sul bottone, facendo apparire una tendina di scelte. Ciascuna scelta della tendina puo' essere stringa di testo o immagine.

Per creare una combo box, si passa in argomento un array di stringhe (o di icone), e si assegna la stringa (icona) inizialmente selezionata:

Combo box sono sensibili a eventi ActionEvent e ItemEvent. Di solito e' sufficiente un ActionListener per gestire una combo box.

Una combo box viene resa editabile chiamando:

Combo box editabile genera un ActionEvent quando l'utente sceglie un elemento dalla tendina e anche quando l'utente preme tasto "enter" nel campo di testo.

Liste

Una lista mostra una serie di elementi disposti in colonna da cui l'utente puo' sceglierne uno o piu'.

La lista ammette selezione di righe singole o multiple. Swing distingue anche fra selezione multipla limitatamente ad un intervallo di righe contigue oppure multipla con piu' intervalli.

Contenuto di una lista puo' essere cambiato dinamicamente.

Per creare una lista in AWT la creo e le aggiungo le righe:

List list = new List(4);
list.add("una");
list.add("due");
list.add("tre");
list.add("quattro");
L'argomento del crostruttore (4) determina lista con 4 linee visibili.

Per creare una lista in Swing devo passare l'array di righe:

String[] scelte = {"una", "due", "tre", "quattro"};
JList list = new JList(scelte);

Per stabilire modo di selezione in AWT scelgo tra singolo e multiplo:

list.setMultipleMode(true/false);

Per stabilire modo di selezione in Swing ho tre possibilita':

list.setSelectionMode(modo);
dove il modo e' uno fra

Lista e' sensibile a eventi di classe ListSelectionEvent. Il corrispondente ListSelectionListener prevede il metodo valueChanged che scatta quando utente esegue una selezione.

Dall'evento di selezione posso ottenere:

Potenziometro (slider)

Consente di introdurre un valore numerico compreso fra un minimo ed un massimo. Barra con cursore mobile. La barra corrisponde ad un intervallo di valori, il cursore ad un valore corrente nell'intervallo.

Per creare uno slider, stabilisco l'orientamento (orizzontale o verticale) e i valori minimo, massimo e corrente (interi):

slider = new JSlider(direzione,minimo,massimo,corrente);
La direzione puo' essere JSlider.HORIZONTAL o JSlider.VERTICAL.

Slider puo' visualizzare righello con due ordini di tacche: maggiore e minore. Ciascun ordine di tacche puo' essere numerato oppure no.

Slider e' sensibile a eventi di classe ChangeEvent. Il corrispondente ChangeListener prevede il metodo stateChanged che scatta quando utente muove il cursore dello slider.

Per leggere i valore corrente dello slider usare getValue(). Per sapere se utente sta ancora muovendo il cursore o ha finito, chiamare getValueIsAdjusting().

Esempio che reagisce solo se utente ha terminato l'interazione:

public void stateChanged(ChangeEvent e)
{
  JSlider source = (JSlider)e.getSource();
  if (!source.getValueIsAdjusting())
    ... fare qualcosa con source.getValue() ...
}

Finestre interne

Per implementare finestre di documento all'interno della finestra principale di un'applicazione.

Devo avere:

Le finestre all'interno del finto schermo hanno decorazioni che forniscono i controlli tipici delle finestre a top-level (chiusura, iconificazione...), ma sono aggiunte e gestite da Swing invece che dal window manager. Per questo, possono differire dalle decorazioni delle finestre top-level (in particolare da quelle della finestra che le contiene).

Creazione

L'esempio ExIntFrame.java crea una finestra (sottoclasse di JFrame) con una finestra interna:

class ExIntFRame extends JFrame
{
  JDesktopPane desktop = null;
  JInternalFrame f1 = null;

  ExIntFRame()
  {
    desktop = new JDesktopPane();
    setContentPane(desktop);
    f1 = new JInternalFrame("titolo 1",true,true,true,true);
    f1.setSize(new Dimension(200,50));
    f1.setVisible(true);
    desktop.add(f1);
    setSize(new Dimension(500,500));
    setVisible(true);
  }
}
Il costruttore della classe ExIntFRame stabilisce che il pannello di contenuto del frame e' un pannello desktop.
Crea f1 finestra interna al mio frame, con possibilita' di essere redimensionata, chiusa, massimizzata ed iconificata (i quattro true nel costruttore), di dimensione 200x50 pixel ed inizialmente mappata (visibile) sul desktop del mio frame.
Stabilisce che le dimensioni del mio frame sono 500x500 pixel cioe' piu' grandi della finestra interna.

In generale f1 invece di essere un JInternalFrame sara' di una sottoclasse di JInternalFrame che definisce anche un contenuto per la finestra interna.

Differenze e similarita' tra frame ed internal frame

La gerarchia di componenti sotto di un JInternalFrame ricalca quella che ho sotto un JFrame. Anche un JInternalFrame ha pannello di contenuto e devo aggiungere componenti al pannello di contenuto.
Anche JInternalFrame ha metodo pack per stabilirne le dimensioni ottimali in base al contenuto. Bisogna sempre assegnare le dimensioni di un internal frame prima di visualizzarlo.

Internal frame non ricevono eventi di finestra (WindowEvent) come i frame, invece ricevono eventi di classe InternalFrameEvent, che sono analoghi.

Supporto predefinito per operazioni particolari

Scelta di un file

Consente di navigare nel file system e scegliere o scrivere il nome di un file.

In AWT:

  1. creare la finestra di dialogo e stabilire se e' finestra per caricamento o per salvataggio di file
    chiediFile = new FileDialog(finestra, "titolo");
    chiediFile.setMode(FileDialog.LOAD
    oppure FileDialog.SAVE);
    dove finestra e' la finestra da cui il dialogo dipende
  2. mostrare il dialogo
    chiediFile.setVisible(true);
    l'interazione con l'utente e' gestita automaticamente dal sistema, finche' utente non chiude il dialogo premendo bottone OK o CANCEL
  3. ottenere il nome del file e, se il nome esiste, prendere il file
    String fileName = chiediFile.getFile();
    String dirName = chiediFile.getDirectory();
    if ( (fileName != null) && (fileName.length()>0) )
    {
    ...aprire file dirName + fileName...
    }

In Swing:

  1. Creare il file chooser
    fc = new JFileChooser();
  2. Chiamare uno dei seguenti metodi che mostrano un dialogo modale contenente il file chooser
    int scelta = fc.showOpenDialog(finestra);
    int scelta = fc.showSaveDialog(finestra);
    int scelta = fc.showDialog(finestra,"titolo");
    dove finestra e' la componente da cui il dialogo deve dipendere.
  3. Leggere il valore di ritorno, che puo' essere JFileChooser.APPROVE_OPTION o JFileChooser.CANCEL_OPTION e, in caso di approvazione, prendere il file
    if (scelta==JFileChooser.APPROVE_OPTION)
    {
    ...aprire il file fc.getSelectedFile().getPath()...
    }
Altri metodi consentono di assegnare directory corrente, definire filtri, personalizzare.

Scelta di un colore (solo Swing)

JColorChooser consente selezione di un colore o da una tavolozza, o mediante terna RGB (rosso, verde, blu) o mediante terna HSB (tinta, saturazione, luminosita').

Non lo vediamo.