Il problema della cancellazione

Si provi ad eseguire il programma PuntiMouse.java, che disegna un rettangolo in ogni punto in cui viene premuto il pulsante del mouse, in questo modo:

Il risultato è che i punti che erano stati in precedenza disegnati sono spariti. Un risultato simile si ottiene con gli altri programmi visti fino ad ora. In particolare, si nota che tutti i disegni che vengono fatti da istruzioni che stanno dentro paint rimangono, mentre i disegni fatti da istruzioni che stanno dentro mouseDown sono spariti. Per esempio, nel programma CrociCerchiLinea.java la linea verticale viene disegnata da paint, e in effetti è l'unica cosa che rimane: tutte le croci e i cerchi, che sono disegnati dentro mouseDown, spariscono quando la finestra viene coperta e poi scoperta di nuovo.

A cosa è dovuto questo curioso fenomeno? Per dare una risposta a questa domanda, è necessario approfondire l'anatomia di un applet. Come abbiamo visto, gli applet hanno questa struttura:

import java.awt.*;

public class nomefile extends java.applet.Applet {
  public boolean mouseDown(Event e, int x, int y) {
    bloccoA
  }

  public void paint(Graphics g) {
    bloccoB
  }
}
Come si è già detto, le istruzioni che si trovano all'interno delle parentesi graffe di mouseDown(..) { ... } sono quelle che vengono eseguite ogni volta che il pulsante del mouse viene premuto. Le istruzioni all'interno delle parentesi graffe di paint(..) { ... } vengono invece eseguite quando si lancia l'applet. Finora si è detto che l'unico momento in cui queste istruzioni vengono eseguite è l'inizio. Questo non è del tutto esatto.

Prima di analizzare questo punto, occorre essere più precisi su quello che succede quando una finestra viene coperta. Quello che in effetti succede è che il contenuto della finestra (quello che è stato disegnato al suo interno) viene cancellato quando la finestra diventa invisibile. Se per esempio si copre la finestra con un'altra finestra, quello che era stato disegnato viene cancellato.

Questo sembra in contraddizione con il fatto che non c'è nessuna cancellazione di quello che è stato disegnato nel paint. Non c'è invece nessuna contraddizione. È semplicemente stata detta una cosa imprecisa a proposito di paint. Non è vero che le sue istruzioni vengono eseguite una sola volta all'inizio. Al contrario,

la sequenza paint viene eseguita ogni volta che parte della finestra diventa visibile
Quando una finestra viene coperta e poi scoperta, i disegni effettuati all'interno di paint vengono cancellati come anche tutti quelli fatti all'interno di mouseDown. Quando la finestra diventa di nuovo visibile, le istruzioni dentro paint vengono eseguite di nuovo, per cui i disegni che sono stati fatti da istruzioni dentro paint vengono semplicemente disegnati di nuovo.

Possiamo dire che non è vero che le cose disegnate da paint rimangono quando la finestra viene coperta e poi scoperta. Quello che succede in realtà è che tutto viene cancellato, solo che i disegni fatti da paint vengono disegnati di nuovo quando la finestra riappare.

Quando l'applet viene lanciato, la finestra diventa visibile e quindi vengono eseguite le istruzioni che stanno fra parentesi graffe in paint(..) { ... }. Ogni volta che la finestra (o una sua parte) diventa invisibile, il contenuto viene cancellato. Quando la finestra torna a essere visibile, le istruzioni del blocco paint vengono eseguite di nuovo, per cui viene fatto di nuovo il disegno.

Riassumendo, possiamo dire che:

Da questo si capisce perchè solo i disegni fatti da mouseDown non riappaiono: quando la finestra diventa di nuovo visibile, solo le istruzioni che stanno dentro paint vengono eseguite di nuovo.