Newsgroup: it.comp.java
Titolo: Sospendere upload ed aggiornare barra progressiva

Prendendo spunto da un'applet trovata su internet sto provando a scrivere
una classe che uplodi un file in ftp e contemporaneamente aggiorni la barra
di progressione.Il codice è:
do{
   available = fileIn.available();
   fileIn.read(dummy, 0, bsize);
   bytesRead = fileSize - available;
   pProgressBar.setValue(bytesRead);
   pStatusTxt.setText(pProgressBar.getString() + " done.");
 
   if(available < bsize)
       bsize = available;
       fileOut.write(dummy, 0, bsize);
  } while(!aborted && available > 0);
Il problema è che la barra non si aggiorna fino a che non è terminato
l'upload visualizzando direttamente il 100%.(L'upload funziona!!).Non sono
assolutamento un 
esperto.Q.no
 mi dà un suggerimento?
Grazie
Vittorio Menascì
--------------------------------
Inviato via 
http://usenet.libero.it

 ha scritto nel messaggio
news:62Z94Z13Z93Y10...@usenet.libero.it...


 come mi sembra che tu già faccia nel tuo codice, aggiornarla >con
"setValue".
La mia impressione sia che il processo di I/O occupi tutta la cpu e non
aggiorni il frame...Possibile?e sopratutto come posso forzare un refresh?


 ha scritto nel messaggio


 > > } while(!aborted && available > 0);
Non so se i miei commenti sono giusti, anche perchè non conosco il contesto
del tuo codice nè soprattutto ciò che viene prima.
Prendili in considerazione, comunque, e fammi sapere...
Magari posti un frammento più grande con qualche tuo commento...
Saluti,
Sergio B.


Sebbene il mittente sia "Sergio", sono sempre io, Sergio B., da un altro
computer :-)
Sergio B.

Ho appena risolto un problema del genere, il problema č che la tua
operazione č lunga, e blocca l'EventDispatchThread, che quindi non
"rinfresca" la tua GUI.
Puoi risolvere il problema in diversi modi:
1. Usi un thread separato e il metodo SwingUtilities.invokeLater()
2. Usi uno SwingWorker
3. Oppure, la soluzione che preferisco, consigliatami da EchelonNSA
(Scusa se non ti ho scritto il nome con i numeri al posto delle
lettere) invece che un while usi dei timer (swing).
Prova ad esempio a creare un timer che genera un evento ogni secondo,
gli fai controllare se l'upload č terminato o abortito e, se non č
cosě gli fai aggiornare la jprogressbar.
(Penso sia conveniente anche dal punto di vista delle prestazioni)
Ciao ciao e spero di esserti stato d'aiuto!


Scusate se posto tagliando 
q.sa
 ma altrimenti ci perdiamo....
Intanto grazie per la consulenza e la competenza con cui rispondete.
Provo a postare tutta la fuzione di upload
private void upload()
    {
       if(!connected)
            return;
        int bsize = 0x13880;
        byte dummy[] = new byte[bsize];
        Socket dataSocket = null;
        try
        {
            FileInputStream fileIn = new FileInputStream(file);
            if(sendFtpCmd("TYPE I"))
                dataSocket = openDataSocket("STOR " + file.getName());
            if(dataSocket != null && statusCode < 400)
            {
               OutputStream fileOut = dataSocket.getOutputStream();
                int fileSize = fileIn.available();
                pProgressBar.setMaximum(fileSize);
 
 
                do
                {
 
                    available = fileIn.available();
                    fileIn.read(dummy, 0, bsize);
                    bytesRead = fileSize - available;
 
			setProgress(bytesRead);
                  	 if(available < bsize)
                        bsize = available;
 
                     fileOut.write(dummy, 0, bsize);
 
 
 
                } while(!aborted && available > 0);
                fileIn.close();
                fileOut.close();
              setProgress(0);
                if(successUrl != null)
                    getAppletContext().showDocument(new URL(successUrl));
                if(aborted)
                {
                    String tmp = socketIn.readLine();
                    socketCon.println("DELE " + localFile.getName());
                    tmp = socketIn.readLine();
                    setStatus("Transfer aborted by User");
                } else
                {
                    setStatus(socketIn.readLine());
                } } else
            {
                setStatus("Upload Failed!");
            }
        }
        catch(MalformedURLException ux) { }
        catch(FileNotFoundException sx)
        {
            appletStatus = "Failed";
            setStatus("File not found!");
        }
        catch(Exception sx)
        {
            appletStatus = "Failed";
            setStatus(sx.toString());
            sx.printStackTrace();
            FileInputStream fileIn = null;
        }
    }
Rispondendo anche a Nuanda69 il riferimento č preciso ma implementare tutto
da zero non č banale, hai forse a disposizione un link di un tutorial?


 da zero non è banale, hai forse a disposizione un link di un tutorial?


complesso da richiedere una soluzione quale quella da lui/lei indicata.
Ciao Sergio!
Intanto informo il news che sono un ragazzo di 20 anni... Nuanda a
"L'attimo Fuggente" ("Se dovessere esistere un Dio dell'amore... beh,
quello deve aver imparato da me, chiamatemi Nuanda":D e 69 è il numero
perfetto dell'amore!:D
A parte questo dilungamento OT non preoccuparti, non mi offendo
affatto, sono un principiante e cerco di aiutare perchè altrimenti mi
sento un "mangia pane a tradimento" ma a volte (spesso) sbaglio!:D
Quello che ho "capito" io è che il problema di aggiornamento della
JProgressBar è un problema di Swing, per via del EventDispatchThread
che viene "bloccato" dall'esecuzione del while (un'operazione lunga)
che blocca il repaint della finestra.
Se ho capito giusto tutta l'interfaccia grafica dovrebbe sembrare
congelata!


--------------------------------
Inviato via 
http://usenet.libero.it

Allora prova a risolvere il problema cosě, sostituisci al posto del
while un timer.
Crei un timer (swing) che generi un evento ogni decimo di secondo, poi
ci aggiungi un ActionListener che gli fa aggiornare la progressbar.
Ora sono di corsa, se non riesci a scrivere il codice posta la
richiesta e oggi pomeriggio con piů calma te lo scrivo!:D
Ora devo andare di corsa a fare la spesa!:D
ciao ciao!

 congelata!
Forse ho capito quello che vuoi dire...e avevi ragione!
Guarda il successivo post di Vittorio...
Tuttavia, io ho ancora qualche dubbio sul perchè di tale comportamento...
Questo è il frammento di codice in cui ho usato la JProgressBar:
for (int i=0; i<size; i+=n)
{
    n=in.read(buffer,0,BUFLEN);
    fout.write(buffer,0,n);
    label.setText((i + " / " + size + " bytes"));
    progressBar.setValue(i);
}
Come vedi la situazione è analoga a quella di Vittorio, e non mi dà
problemi.
Probabilmente accade che Vittorio chiami il metodo upload entro il listener
di un componente della sua GUI, senza inserirlo in un altro thread, ed il
problema non è in questo caso la monopolizzazione della cpu da parte del
ciclo, ma l'uscita dal listener, ritardata fino al termine dell'upload!
In tal modo, infatti, la coda degli eventi si "blocca" in quanto per gestire
gli eventi successivi (l'aggiornamento della progressbar, dei campi
testo...) deve essere terminata la gestione dei precedenti (il listener in
cui viene eseguito l'upload)!
Il tutto si risolve inserendo il metodo upload in un altro thread, che potrà
tranquillamente essere lanciato all'interno di un listener; in tal modo,
continueranno indipendenti l'upload e l'aggiornamento dell'interfaccia
grafica.
Era questo, in dettaglio, che intendevi dire?
O hai qualche altra idea?
Intanto, grazie per l'interessante discussione...fa sempre piacere :-) !
Un saluto,
Sergio B.

 Un saluto,
Un saluto a voi piacere di aver trovato persone competenti e disponibili.
Ciao
Vittorio Menascì


 problema?
No, non penso.
Se hai tempo/voglia (potresti non averne visto che hai già risolto), prova a
mettere il metodo upload che hai postato entro una classe thread, interna
però alla classe del frame principale, dove hai gli oggetti grafici, in modo
da avere accesso a questi (non è l'unica soluzione ma è secondo me la più
semplice); una cosa del genere:
public class MainFrame extends JFrame
{
    // [...]
    private class Uploader extends Thread
    {
        public void run()
        {
            // Inserisci qui il codice di upload() da te postato
        }
    }
    // [...]
}
A questo punto, se il tuo upload è lanciato da un bottone, inserisci
nell'ActionListener di tale bottone il seguente frammento:
Thread t=new Uploader();
t.start();
Tutto dovrebbe andare per il verso giusto.
Fammi sapere...
Il piacere è mio!
Un saluto,
Sergio B.

 3. Oppure, la soluzione che preferisco, consigliatami da EchelonNSA
Esiste un'altra alternativa ed è quella che di solito utilizzo e preferisco.
Guarda in questo sito:
http://foxtrot.sourceforge.net/
Permette di risolvere il tuo problema in modo sincrono (cosa che le prime
due alternative non permettono) ed il tutto è relativamente semplice da
implementare con un piccolissimo impatto sul codice esistente.
Gab.