Wieder Problem mit JProgressBar, wird nicht aktualisiert...



  • Hi! Ich habe da eine Methode die unter gewissen Umständen schon ein bisschen brauchen kann, um ihre Arbeit zu beenden. -> JProgressBar
    In der Methode wird eine while Schleife durchlaufen, ein Durchlauf kann schon mehrere hundert ms dauern, und nach jedem Durchlauf will ich, dass der Ladestreifen 1 % mehr bekommt. Also mache ich das folgender Maßen nach jedem Durchlauf:

    g.load.setValue(i);
    g.load.setString(i + "%");
    g.load.repaint();

    Nur leider passiert nichts. 😞
    Erst nachdem die Funktion zurückkehrt wird der zuletzt gesetzte Wert auch angezeigt. Warum?



  • Ich nehme an, du hast diese Methode und auch das Aktualisieren der Gui im gleichen Thread oder?
    Das Problem ist, dass der Event-Dispatch-Thread durch diese Methode blockiert wird, somit kann auch kein Gui-Update stattfinden.
    Lass daher diese lange Methode in einem neuen Thread ablaufen, dann sollte das klappen.

    MfG

    //edit: habe einen Fehler korrigiert: das Problem liegt am Blockieren des Event-Dispatcher-Threads, welcher in GUI-Applikationen parallel zum Hauptthread läuft -> der Code in der Ereignisbehandlung läuft in diesem Event-Dispatcher-Thread, ruft man in der Ereignisbehandlung nun eine größere Methode auf, wird der Thread blockiert und kann sich nicht mehr um die UI-Events kümmern => deshalb lang laufende Methoden in eigenen Thread auslagern!



  • Mhh sowas habe ich mir auch schon gedacht. Dann wird es wohl daran liegen. Aber mein Versuch das ganze in einem extra Thread laufen zu lassen, ist wohl fehlgeschlagen. Ich habe eine neue Klasse geschrieben und diese von Thread abgeleitet. In der run Methode dieser Klasse habe ich dann einfach die lange Methode ausführen lassen. Der Rückgabewert ist boolean, den habe ich der Klasse einfach als Variable spendiert. Im Hauptprogramm hab ich dann einfach eine Instanz dieser extra Klasse erzeugt und start() aufgerufen. Dann habe ich in einer while Schleife solange gewartet, bis die Variable 'done' der extra Klasse true ist. Ich habe 'done' nach Rückkehren der langen Methode auf true gesetzt. Naja ich dachte mir so würde das alles in einem extra Thread laufen und die Anzeige würde aktualisiert werden. Nur leider hat das nich so geklappt. Das Programm hat eher ziemlich heftig gehangen und sowieso wär mir fast der Rechner abgeschmiert. Jedenfalls musste ich das Programm erst per Taskmanager beenden.

    Also scheinbar kriege ich das nicht hin. Wie kann ich diese Methode richtig in einem anderen Thread abarbeiten?
    Danke!



  • Ist jetzt etwas schwer, das ohne Quelltext nachzuvollziehen, aber ich hab mir das vom Grundprinzip her so vorgestellt:

    public class Test 
    implements Runnable
    {
    
     // ...
    
     public void actionPerformed(ActionEvent e)
     {
      //neuer Thread um GUI updaten zu können
      Thread thread=new Thread(this);
      thread.start();
     }
    
     public void run()
     {
      langeMethode();
     }
    
     public void langeMethode()
     {
      // übelst lange Berechnungen
     }
    
     // ...
    
    }
    

    Eine extra Klasse wäre also gar nicht notwendig.
    Ich hatte dieses Problem nämlich auch mal und habs so gelöst...

    MfG



  • Hab noch was vergessen:

    die GUI sollte übrigens nur durch den Event-Dispatcher-Thread geändert werden und von keinem anderen Thread (Stichwort "Synchronisation"). Von daher sollte man, wenn man die Gui von einem anderen Thread aus beeinflussen möchte, dies über die statische Methode invokeLater(Runnable r) der Klasse "SwingUtilities" erledigen!!
    Diese reiht das übergebene Runnable-Objekt mit den Gui-Aktionen in die Queue des Event-Dispatcher-Threads ein...

    Beispiel:

    // UI-Aktionen in Runnable-Objekt kapseln
    Runnable r = new Runnable() { 
           public void run() 
           { 
                  progressBar.setValue(value); 
           } 
    };
    
    // UI-Aktionen im Event-Dispatcher-Thread ausführen
    SwingUtilities.invokeLater(r);
    

    MfG



  • Danke jetzt klappt alles wunderbar. 🙂


Anmelden zum Antworten