Paola Magillo, Univestita' di Genova, Corso di Interfacce Utente per Informatica, a.a. 2006-2007.

LABORATORIO - INTERFACCE GRAFICHE IN JAVA

Contesto generale

L'obiettivo e' disegnare in Java l'ambiente con le particelle (ved. documentazione del progetto).

In pratica dovete definire un vostro componente Java personalizzato che "si disegna" disegnando su se stesso l'ambiente con le particelle. Tale componente sara' poi inserito all'interno della gerarchia di contenimento della vostra interfaccia, e quindi visualizzato.

La vostra interfaccia, per ora, potra' essere semplicemente una finestra principale (Frame) che contiene come unico sotto-componente questo pannello.
L'ambiente con le particelle da visualizzare potra' essere fisso e costruito da programma (come nel Main di esempio dato nel progetto).

Ci sono vari punti chiave da risolvere:

  1. come scegliere la classe di componente da cui ereditare per definire la nuova classe
  2. come accedere all'ambiente da dentro alla classe nuova che definiamo
  3. come disegnare l'ambiente con le particelle

Non occorre consegnare nulla, questo e' solo un esercizio che vi sara' utile per il progetto finale del corso.

SUGGERIMENTO:
E' molto utile programmare tenendo aperta a fianco una finestra sul sito con il manuale on-line delle classi Java: http://java.sun.com/j2se/1.4.2/docs/api/index.html

1 - Come scegliere la classe di componente da cui ereditare

In genere non e' necessario che l'area destinata a contenere il disegno dell'ambiente con le particelle abbia un comportamento particolare. Quindi possiamo definire la nostra nuova classe semplicemente come sottoclasse di Panel (in AWT) o JPanel (in Swing).

Nel seguito chiamo NOSTRA_CLASSE questa nostra sotto-classe di pannello.

Un pannello in Java non contiene nulla, fino a che non aggiungiamo componenti al suo interno. L'uso che facciamo ora del pannello e' anomalo nel senso che non lo usiamo per contenere altri componenti ma per disegnare sul suo sfondo. Quindi lo usiamo vuoto.
Siccome Java assegna dimensione preferita nulla a un pannello vuoto, e' opportuno ridefinire, nella nostra sotto-classe NOSTRA_CLASSE, la dimensione preferita.
Questa si ridefinisce in Swing chiamando la funzione setPreferredSize (ved. manuale on-line), e in AWT reimplementando la funzione getPreferredSize (ved. manuale on-line) in quanto AWT non fornisce la funzione setPreferredSize.

2 - Come vedere l'ambiente da dentro alla classe nuova

La nostra classe NOSTRA_CLASSE deve poter accedere all'ambiente con le particelle, che sara' un oggetto di classe Environment.

IMPORTANTE:
Quando il nostro componente viene usato nell'interfaccia complessiva del progetto, tipicamente abbiamo gia' un oggetto ambiente, che compare come variabile in qualche altra classe della vostra interfaccia, in genere nella classe che realizza la finestra principale.
La nostra classe (come abbiamo appena detto) avra' anch'essa come variabile un oggetto di classe Environment.
Tale variabile dovra' contenere lo stesso oggetto contenuto nella variabile di classe Environment che sta all'interno della finestra principale.

Il costruttore della nostra classe NOSTRA_CLASSE prendera' in argomento un oggetto di classe Environment e lo assegnera' alla sua variabile interna.
Tale costruttore e' chiamato dal costruttore della classe che corrisponde alla finestra principale dell'interfaccia passando come argomento la variabile di classe Environment che sta all'interno della finestra principale.
In questo modo la finestra principale e il pannello condividono lo stesso ambiente con le particelle.

In pratica, nella classe principale:

  Environment global_env;
  NOSTRA_CLASSE env_panel;
Nella classe NOSTRA_CLASSE da noi definita per disegnare l'ambiente con le particelle:
  Environment local_env;
Il costruttore della classe NOSTRA_CLASSE:
  NOSTRA_CLASSE(Environment env,...)
  {
    local_env = env;
    ...
  }
Nel costruttore dela classe principale:
  global_env = new Environment(...);
  ...
  env_panel = new NOSTRA_CLASSE(global_env...);

3 - Come disegnare l'ambiente con le particelle

Sistemi di coordinate

Le particelle presenti nel nostro ambiente hanno coordinate reali comprese in un generico rettangolo di diagonale (x1,y1)-(x2,y2): questo rettangolo e' il nostro user space.
Il pannello in cui disegnamo ha coordinate intere comprese nel rettangolo (0,0)-(W,H) dove W e H sono larghezza e altezza del pannello in pixel: questo rettangolo e' il nostro device space.

Per poter disegnare, dobbiamo tradurre le coordinate da user space a device space, ovvero portare il rettangolo (x1,y1)-(x2,y2) a coincidere con il rettangolo (0,0)-(W,H) mediante operazioni di traslazione e scalatura.
Questo puo' essere fatto in due modi:

  1. Scrivere una funzione di conversione del tipo int convertX(double x, int W) che, data la x in user space e la larghezza del pannello, restituisce la x in device space; e scrivere un'analoga funzione di conversione per la y. Usare poi queste coordinate convertite per disegnare.
  2. Applicare al pannello una trasformazione di coordinate Java che esegua la traduzione. Poi, si puo' tranquillamente disegnare usando le coordinate espresse in user space.

Disegno vero e proprio

Scandire le particelle presenti nell'ambiente (usare le funzioni getNumber e getParticle della classe Environment).

Ogni particella puo' essere disegnata come un cerchio (funzione fillOval della classe Graphics) o tracciando il contorno (drawOval).
Se si decide di fare entrambe le cose, prima riempire tutti gli interni e poi tracciare tutti i contorni (occorrono due cicli sulle particelle).

In generale ricordare che le cose vengono disegnate nell'ordine in cui sono eseguiti i comandi di disegno, e quello che viene disegnato dopo copre quello che era stato disegnato prima.