# ProgressMonitor



## MonsterBit (10. Mai 2010)

Hallo Leute,

ich bin am verzweifeln. Trotz vieler Beispielen und vielen Stunden googlen sind JProgressBar und ProgressMonitor meine große Schwäche...

Also, mein Problem ist folgendes:
Ich habe ein Programm, welche mir Dateien anhand von Links aus dem Internet runterläd. Das klappt bis jetzt auch wunderbar, nur ich möchte den Fortschritt des Downloads jetzt mit einem ProgressMonitor anzeigen, was mir aber irgendwie schwer fällt.

Ich habe folgenden Code schon zustande gebracht:

```
pm = new ProgressMonitor(mainFrame, "Downloading file...", "", 0, (int) size/1024);
 pm.setMillisToDecideToPopup(0);
 pm.setMillisToPopup(0);
 int progress = 0;

 Thread thread = new Thread (new Runnable() {
     public void run() {
			    		      
       while(!pm.isCanceled() && progress<=pm.getMaximum()) {
		  		    			    		    	   
	    SwingUtilities.invokeLater(new Runnable()
	    {
	        public void run()
	        {
	            pm.setProgress(progress);
		        pm.setNote(progress+" kb of "+size/1024+" done");
		    }
	    });
			    		      
	    try{ 
		//Hier steht der Code, der für den Download sorgt
            } 
	    catch (Exception ex) {}
			    		        
	    progress++;
     }
}
```


Wenn ich den Download dann starte, passiert nichts. Erst wenn die Datei runtergeladen ist, erscheint der ProgressMonitor und zählt einfach nur hoch(zb. ist die Datei 5000kb groß, zählt er von 0 bis 5000)

Wäre nett, wenn mir jemand sage könnte, was ich da falsch mache.

mfg.
MonsterBit


----------



## SlaterB (10. Mai 2010)

was machst du denn mit dem Thread? nirgendwo sieht man seine Verwendung, 
ruhig etwas mehr Code posten

auch wer der Aufrufer ist und was der danach macht, z.B. bis zum Ende der Methode,
wenn der in einer Schleife auf das Ende des Threads wartet, dann ist nix gewonnen


----------



## MonsterBit (10. Mai 2010)

Ach mensch, hab ich vergessen zu posten. Da ist natürlich noch "thread.start();" und die abschließenden Klammern "});"

Also hier nochmal der Code:

```
pm = new ProgressMonitor(mainFrame, "Downloading file...", "", 0, (int) size/1024);
 pm.setMillisToDecideToPopup(0);
 pm.setMillisToPopup(0);
 int progress = 0;

 Thread thread = new Thread (new Runnable() {
     public void run() {
			    		      
       while(!pm.isCanceled() && progress<=pm.getMaximum()) {
		  		    			    		    	   
	    SwingUtilities.invokeLater(new Runnable()
	    {
	        public void run()
	        {
	            pm.setProgress(progress);
		    pm.setNote(progress+" kb of "+size/1024+" done");
		}
	    });
			    		      
	    try 
            { 
		//Hier steh der Code, der für den Download sorgt
            } 
	    catch (Exception ex) {}
			    		        
	    progress++;
      }
   }

}); 
thread.start ();
```

Ansonsten wüsste ich nicht mehr was ich noch an Code posten sollte.

mfg.
MonsterBit


----------



## SlaterB (10. Mai 2010)

läuft folgendes Programm bei dir?

```
public class Test {

	double size = 40000;
	int progress = 0;

	public Test() {
		final ProgressMonitor pm = new ProgressMonitor(null,
				"Downloading file...", "", 0, (int) size / 1024);
		pm.setMillisToDecideToPopup(0);
		pm.setMillisToPopup(0);

		Thread thread = new Thread(new Runnable() {
			public void run() {

				while (!pm.isCanceled() && progress <= pm.getMaximum()) {

					SwingUtilities.invokeLater(new Runnable() {
						public void run() {
							pm.setProgress(progress);
							pm.setNote(progress + " kb of " + size / 1024
									+ " done");
						}
					});

					try {
						Thread.sleep(200);
					} catch (Exception ex) {
					}

					progress++;
				}
			}

		});
		thread.start();
	}

	public static void main(String arg[]) {
		new Test();
	}
}
```

vielleicht machst du was mit der size-Berechnung falsch,

was passiert eigentlich in Zeile 22, findet dort der ganze Download-Vorgang in einem Schleifendurchlauf der while-Schleife statt?
wenn ja dann wird ja wirklich kaum nebenher aktualisiert..

du brauchst wohl eher eine Schleife die die Daten ausliest, und  nebenher den Progressmonitor updatet, 
zeig doch mal was du da so machst


----------



## Gast2 (11. Mai 2010)

Eventuell wäre SwingWorker auch praktischer zu benutzen...


----------



## MonsterBit (11. Mai 2010)

Erstmal vielen Dank für die Antworten

@SlaterB
Dein Programm läuft bei mir einwandfrei. Dort wo dort jetzt "Thread.sleep(200);" steht, müsste doch nach meinem Verständnis der download Code stehen.
Also hier der komplette Code:

```
pm = new ProgressMonitor(mainFrame, "Downloading file...", "", 0, (int) size/1024);
 pm.setMillisToDecideToPopup(0);
 pm.setMillisToPopup(0);
 int progress = 0;
 
 Thread thread = new Thread (new Runnable() {
     public void run() {
                              
       while(!pm.isCanceled() && progress<=pm.getMaximum()) {
                                                       
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                pm.setProgress(progress);
            pm.setNote(progress+" kb of "+size/1024+" done");
        }
        });
                              
        try 
            { 

                  final InputStream is = new BufferedInputStream(urlcon.getInputStream());
		  final OutputStream os =  new BufferedOutputStream(new  FileOutputStream("downloads/test.mp3"));
		  byte[] chunk = new byte[1024];
		  int chunkSize;
		  while ((chunkSize = is.read(chunk)) != -1) 
                  {
		      os.write(chunk, 0, chunkSize);
		  }
		  os.flush();
		  os.close();
		  is.close();             

            } 
        catch (Exception ex) {}
                                
        progress++;
      }
   }
 
}); 
thread.start ();
```



> vielleicht machst du was mit der size-Berechnung falsch,



Daran habe ich auch schon gedacht aber die Größe stimmt immer
Ich ermittle size über die URLConnection:

```
final String sizeStr = urlcon.getHeaderField("Content-Length");
	  final int size;
	   if (sizeStr == null) {
	      // unbekannte Größe
	      size = -1;
	   } else {
		size = Integer.parseInt(sizeStr);
	   }
```

@SirWayne
Den SwingWoker kenne ich jetzt leider nicht. Ich hab mal gegooglet und soweit ich das verstanden haben, braucht man dafür noch eine externe Datei. Falls das jetzt nicht ohne den SwingWorker läuft, versuch ich den später mal. Aber danke für den Tipp.

mfg.
MonsterBit


----------



## SlaterB (11. Mai 2010)

zwischen Zeile 20 und 36 wird doch die komplette Datei gedownloaded, das alles in einem Schleifendurchlauf der while-Schleife, für ein progress++,
wird die Schleife 1000x wiederholt und die Datei 1000x gedownloaded?

> catch (Exception ex) {}
ist dabei auch sehr schlecht, vielleicht erhälst du nach wenigen Downloads direkt hintereinander einen Fehler vom Server
und nur deshalb klappt das ganze,
immer 
e.printStackTrace();
throw new RuntimeException(e);
oder ähnliches schreiben

---------


richtiger wäre, auf die äußere while-Schleife zu verzichten und in der while-Schleife Zeile 27-30, die die ganze Zeit arbeitet,
ab und zu den Progressmonitor zu erhöhen


----------



## Gast2 (11. Mai 2010)

MonsterBit hat gesagt.:


> @SirWayne
> Den SwingWoker kenne ich jetzt leider nicht. Ich hab mal gegooglet und soweit ich das verstanden haben, braucht man dafür noch eine externe Datei. Falls das jetzt nicht ohne den SwingWorker läuft, versuch ich den später mal. Aber danke für den Tipp.
> 
> mfg.
> MonsterBit



Kommt auf deine Java Version an... Der SwingWorker macht nichts was du mit deinem invokeLater machst, also geht es auch auf jeden Fall ohne ...


----------



## MonsterBit (11. Mai 2010)

So, jetzt hab ich die äußere while-Schleife weg gelassen und progress wird in der download-Schleife hochgezählt. Hört sich mich auch logischer an, weil die Datei dann ja wirklich x-mal gedownloadet wird:idea:

Der Code sieht jetzt so aus:

```
Thread thread = new Thread (new Runnable() {
			    		    public void run() {	    		     
			    		    			    		    	   
			    		    	     SwingUtilities.invokeLater(new Runnable()
			    		    	     {
			    		    		       public void run()
			    		    		       {
			    		    		    	  pm.setProgress(progress);
			    		    			      pm.setNote(progress+" kb of "+size/1024+" done");
			    		    		       }
			    		    	     });
			    		      
			    		        try 
			    		        { 
			    		        	 final InputStream is = new BufferedInputStream(urlcon.getInputStream());
			      		    	     final OutputStream os =
			      		    	           new BufferedOutputStream(new FileOutputStream("downloads/test4.pk3"));
			      		    	     byte[] chunk = new byte[1024];
			      		    	     int chunkSize;
			      		    	     while ((chunkSize = is.read(chunk)) != -1) 
			      		    	     {
			      		    	        os.write(chunk, 0, chunkSize);
			      		    	        progress++;
			      		    	        System.out.println(progress);
			      		    	     }
			      		    	     os.flush(); 
			      		    	     os.close();
			      		    	     is.close();
			      		    	     System.out.println("done");
			    		        } 
			    		        catch (Exception ex)
			    		        {
			    		        	ex.printStackTrace();
			    		        }				       
			    		       
			    		    }
			    		    
			    		  });
			    		  thread.start ();
```

Wenn ich den Download jetzt starte, kommt sofort der ProgressMonitor zeigt direkt paar Kbyte an, bleibt aber dann stehen???:L

Stimmt, war nen bissle dumm von mir keine vernüftige Exception Behandlung zu machen, er wirft aber auch keine Exception während des Downloads.

@SirWayne
Gut, dann werde ich es mit invokeLater machen, weil ich es kenne

mfg. MonsterBit


----------



## SlaterB (11. Mai 2010)

die Zeilen 4-11 müssen zwischen 23 und 24 eingefügt/ verschoben werden

nur die int-Variable progress zu erhöhen hat logischerweise überhaupt keine weiteren Auswirkungen,
die Variable wird nicht magisch neu ausgelesen


----------



## MonsterBit (11. Mai 2010)

Jaaa, endlich gehts:toll:
Vielen vielen dank, you made my day!

mfg. 
MonsterBit

EDIT: Doch noch eine kurze Frage:
Damit habe ich die Dateigröße ermittelt:

```
final String sizeStr = urlcon.getHeaderField("Content-Length");
```

Ist es auch möglich genauso einfach den Dateiname zu erfragen, also irgendwie so?

```
final String sizeStr = urlcon.getHeaderField("Content-Name");
```
SO gehts nämlich leider nicht.


----------

