2016-08-05 16 views
1

Ich entschuldige mich für die vielen Fragen zu JProgressBar Update, aber das hat mich wirklich verrückt gemacht.JProgress Bar wird in SwingWorker nicht aktualisiert

Ich habe eine JProgressBar über einen SwingWorker aktualisiert, aber ich habe immer noch das typische Problem der Bar aktualisiert nach Abschluss. Hier

ist der entsprechende Code:

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 
import java.util.ArrayList; 
import java.util.Calendar; 
import java.util.List; 
import java.util.concurrent.ExecutionException; 
import javax.swing.*; 

public class SwingTest { 

    public static void main(String args[]) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       init(); 
      } 
     }); 
    } 

    public static void init() { 
     JFrame frame = new JFrame(); 
     JPanel panel = new JPanel(); 
     JProgressBar bar = new JProgressBar(); 

     JButton button = new JButton("Start"); 
     button.addActionListener(new ActionListener() 
     { 
      @Override 
      public void actionPerformed(ActionEvent e) 
      { 
       bar.setMaximum(100); 
       bar.setValue(0); 

       SwingWorker worker = new SwingWorker<String, Void>() 
       { 
        @Override 
        public String doInBackground() 
        { 
         int val = 0; 
         // +1 to make inclusive 
         for (int i = 0; i < 100; i++) 
         { 
          try 
          { 
           Thread.sleep(50); 
          } catch (InterruptedException e) 
          { 
           e.printStackTrace(); 
          } 

          setProgress(++val); 
         } 

         return "Hello SwingWorker World"; 
        } 

        @Override 
        public void done() 
        { 
        } 
       }; 

       worker.addPropertyChangeListener(
         new PropertyChangeListener() 
         { 
          public void propertyChange(PropertyChangeEvent evt) 
          { 
           if ("progress".equals(evt.getPropertyName())) 
           { 
            bar.setValue((Integer)evt.getNewValue()); 
           } 
          } 
         } 
       ); 

       worker.execute(); 

       try 
       { 
        System.out.println("Return: " + worker.get().toString()); 
       } catch (InterruptedException e1) 
       { 
        e1.printStackTrace(); 
        System.out.println("Failed."); 
       } catch (ExecutionException e1) 
       { 
        e1.printStackTrace(); 
        System.out.println("Failed."); 
       } 
      } 
     }); 

     panel.add(button); 
     panel.add(bar); 

     frame.add(panel); 
     frame.pack(); 
     frame.setSize(200,90); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    } 
} 

Wenn das Problem durch einen anderen Abschnitt wahrscheinlich ist, werde ich meine Frage mit mehr Code bearbeiten, wenn nötig.

Vielen Dank im Voraus.

BEARBEITEN: Code auf ein Minimalprodukt reduziert.

+0

Um eine bessere Hilfe zu erhalten, sollten Sie ein [MCVE] oder [Short, Self Contained, Correct Example] (http://www.sscce.org/) posten. –

Antwort

0

Das Problem in dem Code, den Sie gepostet haben, ist, wenn Sie den SwingWorker starten, warten Sie sofort darauf, dass er ausgeführt wird. Dies blockiert der Ereignis-Thread, das von der Anzeige verhindert aktualisiert:

worker.execute(); // This starts the thread in the background 

try 
{ 
    // This immediately stops the event handler waiting for the worker to finish 
    System.out.println("Return: " + worker.get().toString()); 
} catch (InterruptedException e1) 
{ 
    e1.printStackTrace(); 
    System.out.println("Failed."); 
} catch (ExecutionException e1) 
{ 
    e1.printStackTrace(); 
    System.out.println("Failed."); 
} 

Wenn Sie die Gesamtheit dieses try-catch-Block auf Kommentar, es läuft und die Anzeige aktualisieren.

Wenn Sie auf das Ergebnis des Arbeiters warten müssen, sollten Sie auf die Ergebnisse auf einem anderen Thread warten und den UI-Thread fortsetzen.

+0

Das ist erstaunlich! Vielen Dank! Wenn ich also auf die Ergebnisse eines anderen Threads warte, wie könnte ich dann die Elternfunktion wiederherstellen? Ich stelle mir vor, dass .wait() auch den EDT blockiert. –

+0

Ich habe zum Glück eine Lösung gefunden. Ich musste einfach einen Code umgestalten. Danke noch einmal! –

1

Nun, ich weiß nicht genau, was Ihr Code tut, aber ich sehe nirgendwo in Ihrem Code, wo Sie eine "Verzögerung" haben.

Als Ergebnis wird die Schleife weiter ausgeführt und alle Farbanfragen werden in einer einzigen Anfrage zusammengefasst, so dass Sie nur den endgültigen Wert sehen.

Sie können überprüfen, ob dies das Problem ist, indem Sie einfach eine Thread.sleep() nach der setProgress(...) Methode hinzufügen.

Wenn dies der Fall ist, ist die Frage warum verwenden Sie einen Fortschrittsbalken, da der Code so schnell ausgeführt wird.

Lesen Sie den Abschnitt aus dem Swing-Tutorial auf How to Use Progress Bars und beginnen Sie mit der Arbeitsdemo. Sie können dann den Arbeitscode ändern, um zu sehen, was passiert, wenn Sie Ihre Änderungen vornehmen.

+0

Ich habe meinen Code auf eine minimalere Darstellung bearbeitet. Der vollständige Code kann zwischen einigen Minuten und einer Stunde dauern, um ausgeführt zu werden. Wenn ich Sie verstehe, glaube ich nicht, dass der Code zu schnell ausgeführt wird. –