Paola Magillo, Univestita' di Genova, Corso di Programmazione II per SMID, a.a. 2006-2007.

Lezione 09 a:

UN'INTERFACCIA GRAFICA PER ISTOGRAMMI - PARTE 1

Introduzione generale

Obiettivo

Facciamo un programma per visualizzare istogrammi e compiere operazioni su di essi.

Un istogramma e' un insieme finito e ordinato di rettangoli aventi tutti uguale larghezza (width) e ciascuno la sua propria lunghezza (length).

Le operazioni sono di due tipi: operazioni che avvengono sull'istogramma e operazioni che modificano il modo in cui l'istogramma viene disegnato.

Operazioni sull'istogramma:

  1. Aggiungere un nuovo rettangolo in fondo stabilendo la sua lunghezza
  2. Cancellare l'ultimo rettangolo
  3. Cambiare la lunghezza di un rettangolo
  4. Calcolare grandezze statistiche relative all'istogramma (media, varianza, ecc.)

Operazioni che modificano il modo in cui l'istogramma e' disegnato:

  1. Stabilire il colore di default che viene dato a tutti i rettangoli se non altrimenti specificato
  2. Stabilire il colore proprio di uno specifico rettangolo
  3. stabilire se i numeri corrispondenti alle lunghezze dei rettangoli vengono mostrati o no; in caso affermativo, stabilire se vengono mostrati sopra o sotto ciascun rettangolo
  4. Stabilire il fattore di scala usato per disegnare sulle x e sulle y
  5. Stabilire la posizione dell'asse x nella finestra (se deve essere disegnato piu' in alto o piu' in basso)

Da che cosa partiamo

Sono date le seguenti classi e interfacce Java:

Che cosa dobbiamo fare

Descrizione dettagliata del materiale di partenza

Interfaccia AnyRectangle

File AnyRectangle.java.
Stabilisce che la nostra classe per il rettangolo deve avere i seguenti metodi:

Interfaccia AnyIstogram

File AnyIstogram.java.
Stabilisce che la nostra classe per l'istogramma deve avere i seguenti metodi:

Classe IstoDialog

File IstoDialog.java.
Useremo questa classe cosi' come e', senza modificarla.

Finestra di dialogo (sotto-clases di Dialog) con un numero di campi di testo ciascuno con sua etichetta esplicativa, due bottoni Ok e Cancel per chiudere la finestra.

+----------+----------+----------+ 
|  label1  |  label2  |  label3  | pannello p1 con grid layout
+----------+----------+----------+ 2xK dove K = numero di
|  campo1  |  campo2  |  campo3  | etichette/campi di testo
+----------+----+-----+----------+
|       Ok      |   Cancel       | pannello p2 con grid layout 1x2
+---------------+----------------+
L'utente, guidato da quanto scritto nelle etichette esplicative, immettera' valori nei campi di testo. Poi chiudera' la finestra premendo Ok oppure Cancel.

Il numero di campi di testo e le stringhe da scrivere nelle loro etichette esplicative si decidono all'atto della costruzione di un oggetto di classe IstoDialog. Cosi' come il titolo che dovra' apparire sulla finestra.

Il bottone Cancel semplicemente fa sparire la finestra (comportamento gia' impostato nella classe IstoDialog).
Al bottone Ok bisognera' associare un action listenere per fargli fare quello che ci interessa.

Attributi

L'attributo che interessa a noi e' OkButton = il bottone Ok a cui dovremo associare un action listener.

Costruttori

Metodi

Classe IstoPainter

File IstoPainter.java.
Useremo questa classe cosi' come e', senza modificarla. Non guardiamo come e' fatta dentro, ma solo come si comporta e i metodi interessanti per noi.

E' sottoclasse di Panel, quindi ne eredita le caratteristiche. A differenza pero' di un Panel, che e' pensato per contenere altre cose, un IstoPainter e' pensato per restare vuoto e disegnare un istogramma sul proprio sfondo.
Mentre le dimensioni di un Panel di norma vengono calcolate in base alle dimensioni del contenuto, un IstoPainter stabilisce all'atto della costruzione quali sono le sue dimensioni preferite.
Nota: le dimensioni preferite (ved. lezione 8) verranno poi usate dai layout manager della gerarchia di contenimento in cui si trova per stabilire le sue dimensioni effettive all'interno dell'interfaccia grafica.

I rettangoli dell'istogramma sono disegnati pieni inizialmente usando un colore di default, con il contorno tracciato in grigio chiaro. E' poi possibile assegnare a ciascun rettangolo un suo specifico colore di riempimento.

IstoPainter e' sensibile all'evento di click con il mouse. Come comportamento predefinito, cliccare col mouse su un rettangolo seleziona il rettangolo. L'avvenuta selezione e' segnalata disegnando un contorno piu' spesso al rettangolo selezionato. In ogni istante puo' essere selezionato al piu' un solo rettangolo; selezionare un rettangolo disseleziona l'eventuale altro rettangolo selezionato in precedenza; cliccare fuori dai rettangoli invece non seleziona nulla, ma disseleziona il rettangolo eventualmente selezionato.

La classe IstoPainter prevede un listener apposito (ved. interfaccia SelectionListener) per aggiungere altri comportamenti all'evento di selezione di un rettangolo.

Vediamo ora i metodi interessanti della classe IstoPainter:

Interfaccia SelectionListener

File SelectionListener.java.
L'interfaccia SelectionListener prevede come unico metodo il seguente:

Classe ShowIsto

File ShowIsto.java.
La classe eredita da Frame e realizza la finestra principale dell'applicazione che contiene al centro un pannello per disegno di un istogramma (oggetto di classe IstoPainter), in basso un campo di testo per mostrare messaggi (oggetto di classe TextField), ed e' provvista di barra di menu'. La barra di menu' per ora contiene solo il menu' File con le voci Load, Save, Quit.

+-------------------------------------------------------+
| File                                                  | Barra menu'
+-------------------------------------------------------+
|                                                       |
|                                                       |
|                                                       |
|              IstoPainter                              |
|                                                       |
|                                                       |
|                                                       |
+-------------------------------------------------------+
| TextField per messaggi                                |
+-------------------------------------------------------+

Altre classi interne gestiscono gli eventi di caricamento e salvataggio dell'istogramma.

Della classe ShowIsto vediamo in dettaglio il contenuto perche' dovrete modificarla.

Attributi

Costruttore

Memorizza se stesso nell'attributo thisFrame.
Crea la barra di menu' e la attacca alla finestra.
Crea il menu File e sue voci e lo aggiunge alla barra di menu'.
Stabilisce che l'interno della finestra e' gestito con un layout manager di classe BorderLayout (saranno occupate le posizioni CENTER e SOUTH).
Per la parte centrale, crea un oggetto di classe IstoPainter, che memorizza nell'attributo ip, a questo assegna da disegnare l'istogramma contenuto nell'attributo is (per ora nullo, voi lo dovete cambiare).
Assegna poi alcune caratteristiche di ip: fattori di scala su assi x e y, posizione dell'asse x, dove disegnare i valori delle lunghezze dei rettangoli.
Infine aggiunge ip alla finestra principale in posizione CENTER.
Per la parte inferiore crea la linea di messaggi come oggetto di classe TextField, non editabile, lo memorizza nell'attributo msg e lo aggiunge alla principale in posizione SOUTH.
Impacchetta la finestra.
Finora abbiamo solo l'estetica della finestra. Ora bisogna gestire gli eventi.
Stabilisce il window listener per chiudere la finestra e terminare il programma quando l'utente aziona la x sul bordo (ved. lezione 7).
Stabilisce lo stesso comportamento per il bottone quit, in questo caso pero' occorre usare un action listener.
Ai bottoni load e save associa gli action listener per gestire il caricamento e il salvataggio; questi non appartengono a classi definite "al volo" (come i precedenti), ma sono oggetti di due classi definite a parte (classi interne a ShowIsto): loadListener e SaveListener.

Classi interne

In generale, i listener un po' piu' complicati meritano di essere realizzati con classi a parte, anche per ottenere un codice piu' leggibile.

Le classi LoadListener e SaveListener (entrambe implementanti l'interfaccia ActionListener) definiscono il metodo actionPerformed in modo analogo:

  1. Crea finestra di dialogo di classe IstoDialog, dipendente da questo frame, con titolo "Load" o "Save" (rispettivamente), la finestra conterra' un solo campo con la dicitura "Name of file to load:" o "Name of file to save:" (rispettivamente).
  2. Al bottone Ok di questa finestra di dialogo associa un action listener che e' quello che compie effettivamente l'operazione di caricamento o salvataggio:
    nasconde la finestra di dialogo, recupera il nome del file dal campo di testo presente nella finestra, apre il file e legge/scrive a seconda del caso.
    In caso di caricamento collega il nuovo istogramma al pannello di disegno (ip.setIstogram).
    Le operazioni di lettura/scrittura possono sollevare eccezioni, per questo sono inserite in un blocco try-catch.
    Se ci sono eccezioni viene mostrato un messaggio di errore nella linea messaggi (msg.setText); se va tutto bene viene mostrato un messaggio di operazione compiuta.
  3. Pulisce la linea messaggi e visualizza la finestra di dialogo.
  4. A questo punto il compito del bottone load/save e' finito: il resto del lavoro lo fara' il bottone Ok della finestra di dialogo (tramite l'action listener che associato al punto 2).
Vedremo meglio nella lezione 9b le funzioni Java per lettura/scrittura.

Main

Crea oggetto di classe ShowIsto e lo visualizza.

Materiale da realizzare

Nostra classe per i rettangoli

Facile. Implementare l'interfaccia AnyRectangle ispirandosi alle numerose varianti di rettangolo viste (lezione 2 e lezione 3).
Questa parte e' argomento del laboratorio 4a.

Nota: i metodi sono pubblici nell'interfaccia AnyRectangle, percio' devono essere pubblici anche nella nostra classe rettangolo. La nostra classe puo' avere anche altri metodi (es: area, print...) oltre a quelli previsti da AnyRectangle.

Nostra classe per l'istogramma

Facile. Implementare l'interfaccia AnyIstogram ispirandosi a quanto fatto nell'esercitazione.
Questa parte e' argomento del laboratorio 4a.

Nota: nell'esercitazione si aggiungeva un rettangolo passando all'istogramma solo la length (il rettangolo veniva costruito dall'istogramma). Qui invece passiamo all'istogramma gia' il rettangolo e l'istogramma deve modificare la sua width.

L'interfaccia grafica -- passo 1

Integrare le nostre classi istogramma e rettangolo nella classe ShowIsto fornita.
La classe ShowIsto fornisce gia' una rudimentale visualizzazione di istogrammi. Al momento pero' l'istogramma impostato per essere visualizzato e' nullo, percio' non appare nulla nella finestra.
Creare un istogramma della nostra classe istogramma, aggiungere a tale istogramma alcuni rettangoli della nostra classe rettangolo, e impostare tale istogramma per essere visualizato, invece di quello nullo.
Questa parte e' argomento del laboratorio 4a.

L'interfaccia grafica -- passo 2

Aggiungere alla classe ShowIsto dispositivi per tutte le altre operazioni.

Per fare un buon software, l'ultima cosa e' scrivere il codice! Prima bisogna progettare...
Qui si tratta di esaminare le operazioni richieste e cercare il modo migliore per renderle possibili all'utente.

Decidiamo che il modo migliore e' usare il piu' possibile dei menu'.
Prevediamo allora 4 menu': File Edit View Function da sistemare sulla barra di menu' della finestra principale.
Dove necessario useremo sotto-menu' o finestre di dialogo per chiedere all'utente i parametri delle operazioni.

Menu' File

Ha voci per caricare un istogramma, salvare l'istogramma presente, uscire dal programma.
Esiste gia' nella classe ShowIsto fornita.

Menu' Edit

Ha voci per modificare l'istogramma:

Menu' View

Ha voci per modificare il modo in cui l'istogramma e' disegnato:

Menu' Function

Ha voci che corrispondono al calcolo di caratteristiche dell'istogramma quali media, varianza ecc.

Per adesso siamo in grado di costruire questi menu'. Nella prossima lezione (lezione 9b) vedremo come realizzare i comportamenti da associare alle varie voci.