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

Laboratorio 04:

INTERFACCIA GRAFICA PER IL CRIVELLO DI ERATOSTENE

Vedere l'ultima parte della lezione 4 per l'algoritmo del Crivello di Eratostene in Java.

Realizziamo un'interfaccia grafica per il generatore di numeri primi. L'interfaccia permette di esaminare i candidati uno per uno e, appena uno viene riconosciuto come numero primo, lo mostra. I numeri primi trovati vengono posizionati sullo schermo in fila in ordine di ritrovamento (che e' anche il loro ordine crescente). Si ferma quando sono stati trovati K numeri primi (K prefissato).

Da che cosa partiamo

La classe ViewPNG implementa gia' molto dell'interfaccia. Usa la classe Sieve che avevamo visto nella lezione 4.

Organizzazione dell'interfaccia grafica

Per realizzare l'interfaccia usiamo i seguenti componenti Java:

I componenti sono collocati secondo la seguente gerarchia di contenimento:

              Frame
           (BorderLayout)
                |
  +-------------+---------------------------+
  |             |                           |
  |NORTH        |CENTER                     |SOUTH
Button next  Panel found_panel            Panel p
             (GridLayout 1xK)           (GridLayout 2x1)
                |                           |
         +------+-----+            +--------+-------+
         |...         |            |                |
     Label[] found         Label msg_found  Label msg_candidate

Guardando il codice di ViewPNG

Il costruttore della classe ViewPNG prende in argomento il numero K di numeri primi che vogliamo generare. Questo K serve a dimensionare l'array "found" di etichette destinato a mostrarli.

Le K etichette sono tutte presenti da subito nel pannello found_panel, ma hanno colore di sfondo uguale a quello del pannello e scritta costituita da spazi, percio' non si vedono. Man mano che trovero' i numeri primi, cambiero' il colore e la scritta di queste etichette (ved. dopo).

La classe ViewPNG realizza sia l'interfaccia grafica che il generatore di numeri primi.
Come la classe PNG (generatore senza interfaccia grafica) vista nella lezione 4, ha un puntatore al primo crivello "first" (classe Sieve).
La variabile intera "candidate" tiene il prossimo candidato da esaminare (inizialmente =2).
La variabile intera num_found conta quanti numeri primi sono stati trovati finora (inizialmente =0).

Passando in ordine i numeri candidati a "first" si inneschera' la generazione dei numeri primi.
Il passaggio del prossimo numero primo a "first" viene fatto nella callback del bottone "next". Nella stessa callback, il valore di "candidate" viene incrementato e si aggiorna la scritta mostrata dall'etichetta "msg_candidate".

La funzione "addPrimeNumber" di ViewPNG e' quella che un crivello (classe Sieve) deve chiamare quando ha scoperto che un numero e' primo, con argomento quel numero.
Questa funzione assegna il numero come stringa sulla prima etichetta non ancora utilizzata dell'array found (found[num_found]), cambia i colori di questa etichetta in modo che si distigua dallo sfondo, e incrementa il contatore num_found di numeri primi trovati.
Infine controlla se num_found ha raggiunto il numero K: in quel caso ho trovato tutti i numeri primi previsti e finito, percio' disabilito il bottone "next". Il numero K (che era parametro del costruttore ma non e' stato memorizzato in una variabile), si ritrova come lunghezza dell'array label.

Che cosa bisogna fare

Prima di tutto prendere il file ViewPNG.java.

(1) Collegare il crivello (Sieve) all'interfaccia (ViewPNG)

Ogni crivello, al posto di stampare il numero primo trovato, lo passa all'interfaccia attraverso la funzione addPrimeNumber.
Per questo occorre che ogni crivello conosca il visualizzatore. Aggiungiamo alla classe Sieve una variabile di classe

static ViewPNG view;
In questa variabile, unica e condivisa da tutti i crivelli (perche' di classe e non di istanza), bisogna mettere la nostra interfaccia.
Una soluzione semplice e' chiamare, nel costruttore di ViewPNG, l'istruzione:
   Sieve.view = this;

(2) Chiamare addPrimeNumber da dentro il crivello

Sia n il numero primo corrente. Semplicemente sostituire la funzione di stampa del numero primo, presente nel corpo della funzione filter (classe Sieve), con la chiamata:
   view.addPrimeNumber(n);

Inoltre...

(3) Provare altri layout manager

Provare a usare altri layout manager. Per esempio FlowLayout per il pannello "found_panel".

(4) Leggere K da command-line

Fare si' che il parametro K del costruttore sia letto quando lancio da command-line l'applicazione, invece di essere prefissato a 15 nel codice.

(5) Gestire chiusura della finestra

Fare si' che la chiusura della finestra (agendo col mouse sul bordo) provochi la terminazione del programma. Bisogna gestire l'evento WindowEvent (ved. l'esempio AWTExample, lezione 7).