Paola Magillo, Univestita' di Genova, Corso di Programmazione II per SMID, a.a. 2004-2005.

Lezione 08:

INTERFACCE GRAFICHE IN JAVA - II

Componenti Java

Una interfaccia e' fatta da:

In Java tutti questi sono detti componenti e sono classi che ereditano dalla classe base Component (oppure MenuComponent).

                                 Component
                                     |
          +--------+--------+--------+----------+----------
          |        |        |        |          |           
      Container  Button  Checkbox  Label  TextComponent ...
          |                                     |
  +-------+-----------+                    +----+----+  
  |       |           |                    |         |
Panel  ScrollPane  Window             TextField   TextArea
                      |
                  +---+---+
                  |       |
                Frame   Dialog
                  MenuComponent
                        |
                +-------+--------+
                |                |
             MenuItem          MenuBar
                |
         +------+------+
         |             |
 CheckboxMenuItem    Menu 
                       |
                    PopupMenu

Panoramica sui componenti Java

Citiamo solo i piu' interessanti. Per gli altri e anche per descrizione dettagliata delle classi e dei loro metodi ved. il manuale in linea http://java.sun.com/j2se/1.4.2/docs/api/index.html.

Contenitori Top-level o finestre:

Contenitori intermedi:

Dispositivi inerti (solo grafica, cioe' solo output verso l'utente):

Dispositivi attivi o di controllo (grafica e comportamento, cioe' anche input dall'utente):

Ciascun tipo di dispositivo di controllo e' adatto a ricevere un certo tipo di input.

Gerarchia di contenimento

Un contenitore puo' contenere dispositivi o altri contenitori. Un contenitore intermedio e' contenuto in un altro contenitore, che puo' essere top-level o intermedio.

Si ha una gerarchia di contenimento separata per ogni finestra dell'interfaccia (es: due se ho una finestra principale e una finestra di dialogo).

La gerarchia di contenimento e' descritta da un albero dove la relazione padre-figlio rispecchia la relazione di contenimento.

Nota bene: La "gerarchia" di contenimento rappresenta la relazione di contenimento fra i componenti (componente figlio occupa un'area di schermo "ritagliata" dentro quella del componente padre).
Non ha niente a che vedere con la "gerarchia" delle classi nel paradigma object-oriented (che rappresenta invece la relazione super-classe / sotto-classe).

Ogni contenitore ha un layout manager che stabilisce in che modo gli oggetti devono essere dislocati al suo interno.

Layout Management

Processo di stabilire automaticamente dimensioni e posizione delle componenti all'interno di un contenitore. Ogni contenitore (sia top-level che intermedio) ha un layout manager.

I layout manager sono oggetti di classi che implementano l'interfaccia Java AWT "LayoutManager".

Potrei lavorare senza layout manager, ma allora dovrei fornire posizione assoluta di ogni componente all'interno del contenitore, ed avrei problemi quando il contenitore top-level viene redimensionato dall'utente.

La super-classe Container ha i seguenti metodi, che percio' sono ereditati da tutte le classi di contenitori:

A seconda del tipo di layout manager presente, va usata l'una o l'altra forma del metodo "add".

Classi di layout manager

Esempio

Il programma ExLayout.java accetta Flow, Border, o Grid come opzioni da command line e mostra questi tre layout in azione. Crea 5 etichette con sfondo di colori diversi e le dispone secondo il layout specificato.

Inizialmente impacchetta la finestra nel minimo spazio sufficiente. Quando l'utente cambia le dimensioni alla finestra, il layout manager ne riadatta il contenuto.

FlowLayout (tutti i fila)

I componenti sono messi uno dopo l'altro orizzontalmente finche' ci stanno, poi si va a capo e si forma un'altra linea, ecc.

Costruttori della classe FlowLayout:

Per aggiungere componenti si usa il metodo "add" nella forma senza posizione. I componenti sono messi in fila nello stesso ordine in cui sono aggiunti.

BorderLayout (centro + 4 punti cardinali)

Il contenitore e' diviso in 5 zone:

+--------------------------+
|          NORTH           |
+------+------------+------+
| EAST |   CENTER   | WEST |
+------+------------+------+
|          SOUTH           |      
+--------------------------+

La zona CENTER tende ad occupare tutto lo spazio eccedente quando la finestra viene allargata.

Cosruttori della classe BorderLayout:

Per aggiungere componenti si usa la forma di "add" con la posizione, che e' una fra BorderLayout.NORTH, BorderLayout.SOUTH, BorderLayout.EAST, BorderLayout.WEST, BorderLayout.CENTER.
Il componente viene aggiunto a quella specificata tra le 5 zone.
Va messo un solo componente per zona! E' permesso lasciare vuote alcune zone, che assumeranno dimensione nulla.

GridLayout (griglia)

Il contenitore e' organizzato a tabella con un certo numero di righe e colonne.

Cosruttori della classe GridLayout:

Per aggiungere componenti si usa la forma di "add" senza posizione.
I componenti vengono aggiunti nell'ordine a riempire la griglia riga dopo riga:

+---+---+---+---+
| 1 | 2 | 3 | 4 |
+---+---+---+---+
| 5 | 6 | 7 | 8 |
+---+---+---+---+
Se voglio lasciare vuote delle posizioni, metto come riempitivo una etichetta (classe Label) senza testo.

Generalita' sui componenti Java

Abilitazione e disabilitazione

Un componente puo' essere disabilitato cioe' gli puo' essere impedito di ricevere eventi. Per default e' abilitato.

Di solito si disabilitano i dispositivi di controllo che corrispondono ad opzioni non sensate nello stato corrente dell'applicazione. I dispositivi non attivi sono distinguibili graficamente (es: colore meno intenso).

Metodi della classe Component per abilitazione e disabilitazione:

Dimensioni e allineamenti

Le dimensioni di un componente non sono in genere fissate:

Posso assegnare a un componente delle dimensioni specificate, ma di solito queste non verranno rispettate da Java:

Per assegnare dimensioni e posizione a un componente, Java tiene conto di informazioni fornite dal componente:

Metodi della classe Component:

Java AWT fornisce metodi solo per leggere le dimensioni preferite e gli allineamenti (nome che inizia per "get").
Hanno valori di default (es. per un bottone la dimensione preferita e' quella grande a sufficienza per mostrare tutta l'etichetta e non piu' grande del necessario).
Per cambiare il default l'unico modo e' definire una sotto-classe che re-implementi la funzione "get" corrispondente.

Impacchettamento

I contenitori top-level (finestre) hanno metodo

Da chiamare dopo aver aggiunto tutte le componenti e sottocomponenti alla finestra e prima di renderla visibile.

Usa i layout manager di tutti i contenitori presenti nella gerarchia di contenimento che ha per radice la finestra.

Per la visualizzazione

Le finestre appena costruite sono per default non visibili, le devo rendere visibili da programma con apposita istruzione (setVisible).

Gli altri componenti sono per default visibili all'interno del contenitore che li contiene, purche' questo sia visibile.
Un componente sara' visibile sullo schermo se e' visibile e lo sono anche tutti i contenitori risalendo la gerarchia di contenimento fino alla finestra radice.

Metodi comuni a tutti i componenti (appartengono alla super-classe Component):

Dispositivi in Java

Etichetta

Serve per mostrare informazioni. Esempi: un titolo, un messaggio di istruzioni o di errore.

Classe Java AWT "Label".

Costruttori della classe Label:

Metodi interessanti della classe Label:

Bottone di comando (command button)

Classe Java AWT "Button".

Serve per invocare un'operazione. Esempio: bottone per chiudere una finestra.

Ha l'aspetto di un rettangolo con un'etichetta testuale che indica l'operazione corrispondente.

Sensibile al click del mouse (evento di azionamento del bottone). Durante il click il bottone cambia aspetto per dare feedback che e' stato azionato.

Costruttori della classe Button:

Metodi interessanti della classe Button:

Bottone a due stati (check button o check box)

Classe Java AWT "Checkbox".

Serve per impostare selezione o non selezione di una scelta.

Ha l'aspetto di una casellina (in Java quadrata) con un'etichetta testuale accanto. Il quadrato puo' contenere una crocetta (o altro segno), la cui presenza o assenza denota lo stato della scelta.
Nel suo stato interno ha un valore booleano (selezionato o non selezionato).

Sensibile al click del mouse (evento cambiamento di stato). Al click lo stato del bottone si inverte (da selezionato a non selezionato o viceversa), dandone feedback grafico.

Costruttori della classe Checkbox:

Metodi interessanti della classe Checkbox:

Metodi interessanti della classe ItemEvent, parametro della funzione (callback) itemStateChanged di ItemListener:

Inoltre tutte le classi gli eventi (anche la gia' citata ActionEvent) hanno il metodo:

Gruppi di bottoni a due stati, bottoni radio

Spesso si hanno gruppi di bottoni a due stati, con due possibili politiche:

Un bottone radio e' un check box creato nel contesto di un certo gruppo (il gruppo e' un oggetto di classe CheckboxGroup).
Classe Checkbox ha un costruttore che prende come argomento un gruppo, il bottone viene creato all'interno di quel gruppo. I check box creati nello stesso gruppo lavorano in modo mutuamente esclusivo.

Java distingue graficamente i checkbox indipendenti da quelli che fanno parte di un gruppo radio tramite diversa foma della casellina (rispettivamente un quadrato o un rombetto).

Esempio

Il programma ExButtons.java mostra i tre tipi di bottoni (di comando, check box, radio).

Esercizio: aggiungere la gestione degli eventi (facendo stampare qualcosa su standard output ad ogni bottone).

Campo di testo (text field o text box)

Classe Java AWT "TextField".

Permette l'introduzione di input testuale. Esempio: nome utente per login.

Ha l'aspetto di un'area rettangolare in cui l'utente inserisce il testo. Quando l'utente clicca all'interno dell'area, appare un cursore, i caratteri digitati successivamente sulla tastiera sono diretti al campo di input e vengono mostrati (echo) come feedback.

Sensibile a quando l'utente preme return all'interno dell'area di inserimento (evento di azionamento).

Costruttori della classe TextField:

Metodi interessanti della classe TextField:

Area di testo

Classe Java AWT "TextArea".

Area di testo a piu' linee, eventualmente munita di scroll bar (barre di scorrimento).

La gestione degli eventi e' complessa. Posso gestire anche selezione di parti di testo...

Costruttori della classe TextArea:

Metodi interessanti della classe TextArea:

Esempio

Il programma ExText.java mostra un campo e un'area di testo. L'area di testo riporta ogni volta cio' che l'utente digita nel campo di testo.

Finestre (contenitori top-level) in Java

Java definisce solo l'interno della finestra. A questo il sistema (es. Windows) aggiunge il bordo con barra del titolo, dispositivi di controllo per chiusura, redimensionamento, iconificazione. Queste parti aggiunte si chiamano decorazioni.

Java non ha il controllo sul bordo, lo ha il sistema. Java puo' dare suggerimenti (hints) al sistema, che a sua discrezione li considera oppure no.

Per default il layout manager di una finestra e' BorderLayout.

Una finestra viene creata vuota, le dovro' aggiungere componenti (dispositivi con eventuali contenitori intermedi).

Classe Frame

Finestra adatta ad essere usata come finestra primaria di un'applicazione.
Verra' mostrata dal sistema con tutte le decorazioni.

Costruttori della classe Frame:

Un frame puo' avere una barra di menu' (classe "MenuBar"). Aggiungere la barra di menu' ad un frame:

  menubar = new MenuBar();
  f.setMenubar(menubar);
Alla barra di menu' poi aggiungero' menu'... (ved. dopo)

Contenitori intermedi in Java

Pannelli senza barre di scorrimento

Classe Java AWT "Panel".

Costruttori:

Pannelli con barre di scorrimento

Classe Java AWT "ScrollPane".

Consente di visualizzare (una parte alla volta) un contenuto piu' grande dell'area occupata sullo schermo dal pannello.

Costruttori:

Puo' contenere un solo componente, che si aggiunge con "add".

Il componente contenuto in un pannello a barre di scorrimento deve re-implementare getPreferredSize, altrimenti verra' dimensionato grande quanto il pannello che lo contiene, rendendo inutili le barre di scorrimento.

Nell'esempio ExScrollPane.java e' stata definita una classe LargeLabel che estende la classe Label (etichetta) re-implementando getPreferredSize a 400x400 pixel. Provate a vedere che succede mettendo una Label semplice invece che una LargeLabel.

Menu' e voci di menu' in Java

Menu' permette scelta di un'opzione da una lista di voci prefissata.

Un menu' consiste di:

Esempio: Menu' FILE sulla barra di menu' di una applicazione, permette di scegliere operazioni sui file: creazione, apertura, chiusura, stampa, salvataggio.

Ha l'aspetto di un rettangolo con un'etichetta (titolo del menu'). Quando l'utente preme il mouse sul rettangolo, appare una tendina con una lista di scelte (le voci del menu') rappresentate da etichette testuali.
L'utente si sposta col mouse all'interno della tendina e seleziona la voce desiderata.
La selezione genera un evento.

I tipi di voci di menu' ricalcano i tipi di bottoni (di commando o a due stati).
Una voce a due stati ha associato un riquadro o altro elemento grafico (visualizzato di lato) che puo' essere selezionato oppure no.

Tipi di menu'

Un menu' puo' essere:

Classi in Java AWT:

Costruzione di menu'

1) Costruisco un menu' vuoto, costruisco le voci e le aggiungo al menu':

  menu1 = new Menu("Primo menu'");
  menu1.add (new MenuItem("voce semplice"));
  menu1.add (new CheckboxMenuItem("voce a due stati"));
Crea un menu' con de voci: una semplice, una a check box.
Il menu' non e' ancora collegato al resto dell'interfaccia.

2a) Inserisco il menu' sulla barra di menu' di una finestra:

  bar = new MenuBar();
  frame.setMenuBar(bar);
  bar.add(menu1);
Posso costruire altri menu' e aggiungerli alla barra. Saranno aggiunti in ordine da sinistra verso destra.

2b) Inserisco invece il menu' come sotto-menu' di un altro, realizzando in tal modo un menu' a cascata. Basta aggiungerlo come se fosse una voce di menu':

  menu2 = new Menu("super menu'");
  menu2.add (menu1);
  menu2.add("una voce");  
  menu2.add("altra voce");
Adesso sara' menu2 che dovro' aggiungere alla barra.

Eventi nei menu'

Quelle che reagiscono a eventi sono le singole voci dei menu'.

Le voci che sono sottomenu' le gestisce automaticamente il sistema (la loro reazione e' mostrare la tendina del sottomenu').

Esempio

Il programma ExMenu.java costruisce una finestra con tre menu': due posti sulla barra e uno posto come sotto-menu' del primo di questi. Ogni scelta ha come callback la stampa dell'etichetta della voce di menu' selezionata.