|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Member
Iscritto dal: Aug 2004
Messaggi: 83
|
[JAVA]Componente progress bar sfarfalla
Ho creato un programmino che effettua l'FTP comprensivo di stato di avanzamento del processo tramite componente JProgressBar.
La progress bar l'ho inserita all'interno di un ciclo while che invia byte per byte il file. Il problema è l'effetto sfarfallio che si ottiene quando viene ridisegnata ogni volta la progress bar. while (true) { c = is.read(); // LEGGO DAL FILE BYTE PER BYTE if (c < 0) break; os.write(c); numByte++; percentualeStatus = (int)Math.round(((numByte) / byteTotal) * 100); if (percentualeStatus != percentualeStatusOld) { jProgressBarFTP.setValue(percentualeStatus); // SETTO IL VALORE IN PERCENTUALE percentualeStatusOld = percentualeStatus; jProgressBarFTP.paint(jProgressBarFTP.getGraphics()); //RIDISEGNO IL COMPONENTE } } Come posso togliere lo sfarfallio? Per mezzo di un thread? Ma in corrispondenza solo del ridisegnamento del componente? Aiuto, grazie.
__________________
SoftOXY!2004 |
|
|
|
|
|
#2 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
|
Quote:
in effetti e' la soluzione migliore: crei un nuovo thread ed all'interno di quest'ultimo esegui le operazione di lettura dalla rete, mentre il thread principale sara' libero di rinfrescare la tua progress bar. In questo modo non solo elimini la paint(), causa dei tuoi problemi: puoi anche integrare la tua progress bar in un dialogo/frame con un bottone "Cancella" per fermare l'esecuzione (ti basta una semplice variabile booleana). High Flying Sottovento
__________________
In God we trust; all others bring data |
|
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Questa riga
jProgressBarFTP.paint(jProgressBarFTP.getGraphics()); //RIDISEGNO IL COMPONENTE è un po' anomala. L'invocazione di setValue provvede in via autonoma ad aggiornare l'aspetto della barra di progresso. Nel caso in cui non provveda c'è qualcosa che non va. Una svista tipica è l'invocazione di "setValue" ad opera di un Thread diverso dallo AWT Event Dispatcher Thread. E' possibile (solo possibile) che sia il tuo caso perchè leggo che maneggi byte lungo un flusso, cosa a cui si deve dedicare un Thread certamente diverso dall'Event Dispatcher. In questo caso circondi l'invocazione che aggiorna il componente AWT/Swing con uno: Codice:
//final value = percentualeStatus;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
jProgressBarFTP.setValue(value);
}
});
|
|
|
|
|
|
#4 |
|
Member
Iscritto dal: Aug 2004
Messaggi: 83
|
.............
Grazie per le risposte.
Avevo già provato a far girare il ciclo while() all'interno di un thread, ma non funziona. Mi da lo stesso errore se inserisco il pezzo di codice suggeritomi da PGI-Bis, errore di scrittura sul socket e mi blocca la rete. Non posso più accedere alla rete. Come posso ripristinare lo stato iniziale? Io ho provato con net stop e net start, ma non ha effetto, devo riavviare la macchina per avere risultati. Bà????
__________________
SoftOXY!2004 |
|
|
|
|
|
#5 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
|
Quote:
Cmq alcuni suggerimenti: - per quanto riguarda lo spostamento del ciclo while all'interno di un thread, e' la soluzione che adotto praticamente sempre. Non ho voglia di inventare cose nuove, per cui uso sempre quella in quanto e' semplice e robusta. - Ovviamente l'apertura di un eventuale dialogo di attesa, con la relativa JProgressBar NON deve esser fatta in quel thread: se vuoi aprire una simile finestra, lo dovrai fare dal thread principale. - La rete non viene influenzata da questo. Pubblica il codice, vediamo di risolvere. Beh, a dire il vero ora vado a dormire, ma su questo forum c'e' sicuramente gente molto piu' in gamba di me che ti sa aiutare.... High Flying Sottovento
__________________
In God we trust; all others bring data |
|
|
|
|
|
|
#6 |
|
Member
Iscritto dal: Aug 2004
Messaggi: 83
|
..............
ok, non sono d'accordo sul mettere tutto il codice, perchè penso che sia fastidioso leggere tutte queste righe, ma se tu mi dici che le leggeranno...
metto solo il metodo che implementa l'invio del file in ftp, la jProgressBar è nella classe che richiama questo metodo: private void inviaFileFTP (String pathFile) { double byteTotal = 0; String fileName = ""; int errorConnect; int percentualeStatusOld = 0; errorConnect = FTPConnect (utente.getFtpConfig().getHost(), utente.getFtpConfig().getUser(), utente.getFtpConfig().getPass()); if (errorConnect > 0 && errorConnect != 230) { return ; } String file_da_aprire = pathFile; File inputFile = new File(file_da_aprire); byteTotal = inputFile.length(); fileName = inputFile.getName(); textAreaFTP.append("transfert: " + fileName + " " + String.valueOf(byteTotal) + " byte\r\n"); OutputStream os = null; FileInputStream is = null; try { ftp.setFileType( FTPClient.BINARY_FILE_TYPE ); int indexToken = fileName.lastIndexOf("."); String ext = fileName.substring(indexToken); newNameFile = "FILE_" + DateUtilities.getString(materiale.getDataPubblicazione()) + ext; os = ftp.storeFileStream(newNameFile); is= new FileInputStream( file_da_aprire); int c; int numByte = 0; jProgressBarFTP.setValue(0); jProgressBarFTP.setStringPainted(true); while (true) { c = is.read(); if (c < 0) break; os.write(c); numByte++; final int percentualeStatus = (int)Math.round(((numByte) / byteTotal) * 100); //textField1.setText(String.valueOf(numBuyte)); //System.out.println(percentualeStatuts); if (percentualeStatus != percentualeStatusOld) { jProgressBarFTP.setValue(percentualeStatus); /* SwingUtilities.invokeLater(new Runnable() { public void run() { jProgressBarFTP.setValue(percentualeStatus); } }); */ percentualeStatusOld = percentualeStatus; //jProgressBarFTP.paint(jProgressBarFTP.getGraphics()); } } //InviaFile iFile = new InviaFile(is, os, jProgressBarFTP, byteTotal); //Thread t = new Thread(iFile); //t.run(); os.close(); is.close(); textAreaFTP.append(ftp.getReplyString()); } catch (Throwable t) { MessageDialog.throwable(this, t); } FTPDisconnect (); } }
__________________
SoftOXY!2004 Ultima modifica di softoxy : 10-05-2006 alle 17:01. |
|
|
|
|
|
#7 | ||
|
Senior Member
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
|
Quote:
Quote:
In alternativa, usa il codice di PGI-Bis, ma ti consiglio vivamente di fare questa funzione in un thread separato. Si tratta di poco lavoro.... Per quanto riguarda la rete, non vedo alcun problema. Purtroppo non ho il tempo di fare prove... High Flying Sottovento
__________________
In God we trust; all others bring data |
||
|
|
|
|
|
#8 |
|
Member
Iscritto dal: Aug 2004
Messaggi: 83
|
..........
Grazie, grazie ancora.
Eppure ogni volta che metto il codice di PGI o se vedi la parte commentata c'era un therad che faceva il ciclo, mi blocca la rete. I canali os e is li chiudo, forse devo chiuderli all'interno del thread, adesso provo Ancora grazie.
__________________
SoftOXY!2004 Ultima modifica di softoxy : 10-05-2006 alle 17:30. |
|
|
|
|
|
#9 |
|
Member
Iscritto dal: Aug 2004
Messaggi: 83
|
.........
si funziona, mettendo la chiusura dei canali is ed os all'interno del thread l'invio del file avviene e si chiudono senza bloccarmi la rete, solamente il thread sembra essere sempre bloccante, perchè la jProgressBar non si visualizza se non alla fine (100%).
__________________
SoftOXY!2004 |
|
|
|
|
|
#10 |
|
Member
Iscritto dal: Aug 2004
Messaggi: 83
|
............
La classe InviaFile
package it.computime.object; import cfc.swing.MessageDialog; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import javax.swing.JOptionPane; import javax.swing.JProgressBar; public class InviaFile implements Runnable { int c; int numByte = 0; int percentualeStatus = 0, percentualeStatusOld = 0; FileInputStream is = null; OutputStream os = null ; JProgressBar jProgressBar = null; double byteTotal = 0; public InviaFile(FileInputStream is, OutputStream os, JProgressBar jProgressBar, double byteTotal) { this.is = is; this.os = os; this.jProgressBar = jProgressBar; this.byteTotal = byteTotal; } public void run() { try { while (true) { c = is.read(); if (c < 0) break; os.write(c); numByte++; percentualeStatus = (int)Math.round(((numByte) / byteTotal) * 100); if (percentualeStatus != percentualeStatusOld) { jProgressBar.setValue(percentualeStatus); percentualeStatusOld = percentualeStatus; jProgressBar.repaint(); } } os.close(); is.close(); } catch (IOException e) { JOptionPane.showMessageDialog(null, e); } } }
__________________
SoftOXY!2004 |
|
|
|
|
|
#11 |
|
Member
Iscritto dal: Aug 2004
Messaggi: 83
|
......
.l'errore è nel far partire il thread con run, ecco perchè è bloccante.
Devo farlo partire con il metodo start(), però mi dice "Bad File Descriptor" eppure il file è is............?????
__________________
SoftOXY!2004 |
|
|
|
|
|
#12 |
|
Member
Iscritto dal: Aug 2004
Messaggi: 83
|
........
forse ho capito, perchè chiuso subito il canale, il thread parte e io gli chiudo il canale sotto... il puzzle si chiude!
__________________
SoftOXY!2004 |
|
|
|
|
|
#13 |
|
Member
Iscritto dal: Aug 2004
Messaggi: 83
|
Risolto.
Ho sbagliato di concetto. Io pensavo di dover mettere nel thread solo il ciclo while, ma da come si vede nel metodo, si aprono canali e si chiudono al termine dell'operazione. Mettendo tutte le operazioni del metodo all'interno del thread e spostando l'intero controllo dell'operazione al thread, funziona tutto benissimo. E' vero, la finestra principale ha la possibilità di ridisegnarsi, quindi spostando anche la finsestra la progressBar non sfarfalla (utilizzando solamente setValue()) e indica il progresso del processo. Grazie per i fantastici aiuti.
__________________
SoftOXY!2004 |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 16:45.



















