# JProgressBar + Thread + Client



## Gast (30. Dez 2005)

HI!!

Ich würde euch kurz mal um Hilfe bitten:
Ich habe Einen Server / Client geschreiben mit dessen Hilfe man files versenden kann. Zustäzlich wollte ich eine JProgressBar einfügen (= im Hauptfenster), was auch funktioniert:

```
private JProgressBar m_prBar;
// ... funktionen uws
// Einbau der JProgressBar ins JFrame
m_prBar = new JProgressBar(0,100); 
m_prBar.setStringPainted(true);
jpanel2.add(m_prBar);

// Fenster wir zusamengebaut.
```

Im weiteren Programm Teil rufe ich den Cleint auf der die Daten an den server schickt ( dabei übergebe ich die JProgressbar mit)


```
// m_ip ... = die Ziel ip
// FTO.getfreadpfad() = quelladresse der datei
// m_prBar = JProgress Bar
RClient client= new RClient(m_ip, FTO.getfreadpfad(), m_port.getText(), m_prBar);
client.runClient();
```

Im Client verwende ich einen Thread mit dessen hilfe ich die verschieckte datenmenge berechne
und hier möchte ich dei Progressbar aktualisieren

```
// Thread kreieren
new Thread()
            {   
                public void run()
                {  long lcurrent= 0;
                    int i = 0;
                    while(calc_bar)
                    {   File f = new File(m_pfad);
                        long lmax = f.length();
                        // Berechnung  und den Procentualen wert in JProgressBar einfügen                      
                        m_prBar.setValue(wert);
                        m_prBar.validate();
                        m_prBar.repaint();
                     
                    }
                }
              }.start();
//Thread beendet  
// Socket und Datentransfer      
            clientSocket = new Socket(InetAddress.getByName(m_ip), m_port);
            OutputStream out = clientSocket.getOutputStream();
            InputStream in = new FileInputStream(m_pfad);
            byte[] buffer = new byte[1024];
            int n;

             while ((n = in.read(buffer)) != -1)
            {
                out.write(buffer, 0, n);
             
            }
            in.close();
            out.close();   
            calc_bar=false;
        }
```
Das Problem ist er führt den Thread korrekt aus jedoch wird die JProgressBar im Hauptprogramm erst nach beenden der Datenübertragung aktualisiert.
Wieso? wenn ich sie hier repainte? Wie kann man das Problem lösen thx für eure hilfe


----------



## MPW (31. Dez 2005)

Ein Problem von Swing ist nicht Threadsicher, du musst das mit einer EventQueue.invokeAndWait machen.


----------



## Gast (31. Dez 2005)

Und wie kann man das mit dem EventQue.invokeAndWait lösen


----------



## Roar (31. Dez 2005)

so: http://www.java-forum.org/de/viewtopic.php?t=8101


----------



## Gast (31. Dez 2005)

Das funktioniert schön und gut solange man keinen Server in die Ver scheibung der ProgressBar einbaut also:

solange in der Klasse Algorithmus nur:

```
while( current <= end && !isInterrupted() ){ 
         try{ 
            Thread.sleep( 100 ); // Kurz warten 
         } 
         catch( InterruptedException e ){ 
         } 
         setValue( current++ ); // Hey! Es ist was passiert! 
      }
```
wenn da jedoch einen Server einbaut(funktioniert es nicht ) also wenn zB: 

```
try
{
InputStream in = verbindungsSocket.getInputStream();
OutputStream out = new FileOutputStream(pfad);     
byte [] buffer = new byte [1024];
int n;

int fsize = in.read();

while ((n = in.read(buffer)) != -1 )
{ if(current <= end && !isInterrupted())
                    {
                    
                        try{ 
                            Thread.sleep( 100 ); // Kurz warten 
                        } 
                        catch( InterruptedException e ){ 
                       }
                        current ++;
                    }
                     this.setValue( current); // Hey! Es ist was passiert! 
                    out.write(buffer,0,n);
                  } 
 }
```
und hier die dazugeöhrigen catch funktioniert es nicht mehr
woran kann das liegen


----------



## MPW (1. Jan 2006)

Also irgendwie hast du das ein bisschen komisch gemacht,
die schleife kann noch weiterlaufen, aber der Inhalt muss nicht umbedingt noch ausgeführt werden; für meinen Geschmack ist das schlechter Stiehl.

Was genau ist end, die länge von buffer, oder wie?

Es kann passieren, dass der Thread interrupted wird, aber die Schleife läuft dann noch weiter, das macht keinen Sinn.

Hängt doch mal die Bedinngungen aus dem if mit && noch in den while-kopf, oder ist das Absicht, das trotzdem noch alles eingelesen wird?

Noch was:
Deine Klasse erbt von JProgressBar?

```
this.setValue(current);
//eigentlich reicht doch dann:
setValue(current);
```


Setz mal da irgendwo ein System.out.println() rein, ich hab' das Gefühl, das das Problem nicht die Progressbar selbst ist, da läuft glaube ich noch was anderes schief.

[edit:] Es kann aber rein theoretisch auch sein, dass die JVM das einlesen für wichtiger hält, und deswegen die ProgressBar nicht aktualisiert wird! In dem Falle müsstest du doch mit der EventQueue arbeiten. [/edit]


----------



## Gast (1. Jan 2006)

Schau es ist so: (ich habe es so gemacht wie das muster bei diesem Link http://www.java-forum.org/de/viewtopic.php?t=8101)
Ich habe eine Klasse Server welche von Runnable erbt diese Startet dann die Klasse algorithmus welche unter dem oben angefürten link steht. Dort füge ich dann den wirklichen Server quellkod ein d.h. ich starte den Server mit dem oben angeführten Code. Das mit der Schleife ist vorerst absichtlich so gemacht denn wenn ich den && Befehl in den Schleifenkopf gebe wird das File nie 100% übertragen und eine Exception wird geworfen. Das Problem ist aber Folgenden: Ich habe einen System.out.println("ZEICHNE MICH"); befehl reingegeben und das Problem ist: der wird ausgegeben woraus folg das die Schleife und der Rest passt. wenn du Debuggst wird es auch korrekt ausgeführt und setValue(current) wird ebenfalls aufgefruffen und ausgeführt nur die GUI zeichnet es nicht. Es kann daran Liegen wie du sagtest das der eingentliche Servercode wichtiger ist als die GUI. Ich habe keine Ahnung wieso das nicht funkt.


----------



## MPW (1. Jan 2006)

Das funzt nicht, weil Swing nicht Threadsicher ist, wie bereits ich und einige andere hier in diesem Thread gesagt haben.

Versuch's mal mit java.awt.EventQueue.invokeAneWait() wie im Tutorial beschrieben ist!

[edit:] Aber die Progressbar, selbst wenn sie dann mal richtig gezeichnet wird, wird mit deiner Schleifenkonstruktion sowieso nie richtig funktionieren, aber das ist ein Problem, was ich erst im zweiten Schritt lösen würde.


----------



## Gast (1. Jan 2006)

Sie wird korrekt angezeigt nur nicht aktualisiert EventQueue.invokeAndWait() verwende ich bereits wenn ich die aktualsierung parallell zum empfang der daten machen will also in dieser Schliefe
while ((n = in.read(buffer)) != -1 ) 
{
//Aktualisieren
}
wird sie nicht aktualisiert funktionen ausgeführt Balken nicht gezeichnet wenn ich zuerst daten schicke obere Schleife
und dann den Balken Aktualisierte (andere schleife mit thread also 1 sek warten zeichnen dann funkt es  entweder ich bin zu dumm um das richtig einzubauen oder es ist wirklich so das der Server die höhere Priorität hat


----------



## MPW (1. Jan 2006)

Sorry, kannst du die letzten drei Zeilen nochmal neu formulieren, ich steig' da nicht durch.


----------



## Gast (2. Jan 2006)

Also ich habe das Problem gelöst.
Ich wollte das die JProgessBar / ProgressMonitor automatisch die größe der empfangenen / gesendeten Datei anzeigt.
Bis jetzt funtkioniert bei mir nur der Folgende Lösungsweg wirklich:
1) Server als Thread (logisch)
2) Client als Thread(auch logisch)
3) Sobald der Client / Server läuft muss man von dort aus mit Hilfe einer set Funktion, die man selber schreibt auf eine andere Klasse zugreifen. Diese Andere Klasse sollte die JProgessBar oder halt den ProgessMonitor beinhalten. Falls man keine externe setfunktion einer anderen Klasse aufruft sonder einfach in dem Client / Server Thread den Wert setzen läst so wird das nicht druchgeführt. Dabei hilft auch EventQueue.invokeAndWait() nicht weiter, AUSER: die JProgessBar / ProgessMonitor wird in einem weiteren eigenen Thread gestartet. EventQueue.invokeAndWait() kann man verwenden wenn in dem Client / Server Thread die JProgessBar oder der ProgessMonitor ein einem eigenen Thread gesetzt wird ansonsten, also wenn ohne eigenen Thread (empfangen & setzen) funktioniert es nicht. Wahrscheinlich gibt es auch eine einfachere Lösung.


----------

