Newsgroup: it.comp.java
Titolo: repaint che non funziona

Avevo pensato di inserire in un frame un'immagine (Canvas) mentre
vengono scambiati dei dati con il server, più che altro per una
ragione estetica.
Il problema è che il metodo paint viene, di fatto, eseguito, solo
quando è finito lo scambio dei dati (e, quindi, non serve più). In
altre parole, il Component con l'immagine viene rimosso prima ancora di
essere visualizzato, qualunque sia il tempo di attesa.
C'è un modo per obbligare ad eseguire un paint PRIMA dell'esecuzione
del seguito di un metodo? Ho provato con repaint(), repaint(100),
persino con un thread separato che gestisse il Component, o,
alternativamente, lo scambio di dati, ma inutilmente.
Marco
N.B. uso awt, non swing.

 del seguito di un metodo?
Dunque: cercando in giro, ho scoperto la causa (ma non la soluzione)
del mio problema: repaint() non esegue direttamente il paint richiesto,
ma accoda la richiesta ad un thread di sistema che si occupa della
grafica, che esegue il paint quando possibile. Ovvero, se è ancora
richiesta l'esecuzione di ulteriore codice, mai.
Ora, supponiamo di avere la seguente classe:
public class attesa extends Canvas
 {
  private Image sfondo;
  private int dimx;
  private int dimy;
  public attesa(int dimx,int dimy,Image sfondo)
   {
    super();
    this.dimx=dimx;
    this.dimy=dimy;
    this.sfondo=sfondo;
   }
  public void paint(Graphics g)
   {
System.out.println("paint");
    try
     {
      MediaTracker track=new MediaTracker(this);
      track.addImage(sfondo,0);
      track.waitForID(0);
     }
    catch(InterruptedException e) {System.out.println("Errore");};
    g.drawImage(sfondo,0,0,dimx,dimy,this);
System.out.println("Fatto");
   }
 }
... e supponiamo di istanziarla nel modo seguente:
//*** creazione, visualizzazione frame (java.awt.frame) e inserimento
Label, Button e quant'altro con relativi ascoltatori
//segue la porzione di codice interna all'ascoltatore di un singolo
Button
//....
        frame.removeAll();
        frame.setTitle("Attendere");//questo funziona
        Panel pannello=new Panel();
        pannello.setLayout(new GridLayout(1,2));
        Label avviso=new Label("Un momento, per favore");
        pannello.add(avviso);//questo funziona solo in alcune
piattaforme
        attesa Attesa=new attesa(400,300,sfondo);//immagine definita in
precedenza
        pannello.add(Attesa);//questo non funziona mai
        frame.add("Center",pannello);
        metodo_che_elebora_vari_dati_mettendoci_qualche_secondo();
        frame.removeAll();//eleborazione completata, non serve più
l'immagine di sfondo, si passa alla visualizzazione dei risultati
        // aggiunta nuovi elementi al frame
Il risultato è che non viene mai visualizzata l'immagine "sfondo" come
richiesto, in quanto la richiesta di visualizzazione parte quando ormai
è stata rimossa la Canvas. Infatti, nessun output compare a schermo
(paint mai eseguito).
Ho provato a inserire le seguenti righe dopo il
"frame.add("Center",pannello);":
avviso.paint(avviso.getGraphics());
Attesa.paint(Attesa.getGraphics());
Finalmente, il paint viene eseguito (compaiono le scritte "paint" e
Fatto" sulla console), ma il risultato è lo stesso: NON SI VEDE NULLA
(?!?!?!?!?!?).
Se tolgo l'ultimo frame.removeAll(), alla fine l'immagine e la scritta
vengono correttamente visualizzati (ma ovviamente non serve più, anzi
impiccia), per cui il problema è proprio come obbligare java ad
eseguire  SUBITO l'effettivo aggiornamento del frame, senza
aspettare... all'infinito: se inserisco nella classe attesa un boolean
che viene settato a true dal paint, e inserisco nell'ascoltatore un
ciclo che aspetta sia impostato a true, entro in un loop infinito!
Qualche suggerimento?
Marco

 del seguito di un metodo?
Allego un esempio completo per spiegare meglio il priblema:
L'output deve essere "writed Wait", poi "writed Done", e
dovrebbero essere visualizzate sul Frame prima la scritta "Wait", poi
"Done". Ma vedo solo "Done" e
"writed Done" alla fine dell'esecuzione.
import java.awt.*;
import java.awt.event.*;
class test
 {
  public static void main(String[]args)
   {new window();}
 }
class window extends Frame
 {
  private int max=10;
  private void work(write w)
   {
    long stop=(new java.util.Date()).getTime()+max*1000;
    while (((new java.util.Date()).getTime()<stop)&&(!w.done)) {}
//aspetto l'esecuzione di paint, con un max di 10 secondi
//non esco mai dal loop a causa di w.done==true!!!!!!
//qui eseguo metodo_che_elebora_vari_dati_mettendoci_qualche_secondo();
   }
  public window()
   {
    super();
    setSize(100,100);
    setLocation(200,200);
    Button b=new Button("Push");
    done a=new done();
    b.addActionListener(a);
    add("Center",b);
    addWindowListener
     (
      new WindowAdapter()
       {
        public void windowClosing(WindowEvent e)
         {System.exit(0);}
       }
     );
    setVisible(true);
   }
//inner class
  class done implements ActionListener
   {
    public void actionPerformed (ActionEvent e)
     {
      removeAll();
      write wait=new write(100,100,"Wait");
      add("Center",wait);
      wait.repaint();
      validate();
      repaint();
      work(wait);
      removeAll();
      write done=new write(100,100,"Done");
      add("Center",done);
      validate();
      repaint();
     }
   }
 }
//Component che visualizza un'immagine; per semplicità ho inserito
solo una stringa
class write extends Canvas
 {
  private String phrase;
  public boolean done;
  public write(int dimx,int dimy,String phrase)
   {
    super();
    setSize(dimx,dimy);
    this.phrase=phrase;
    done=false;
   }
  public void paint(Graphics g)
   {
    g.drawString(phrase,20,30);
    done=true;
    System.out.println("paint finished: writed "+phrase);
   }
 }