2013-11-28 27 views
9

Próbuję uzyskać pasek postępu, aby dokładnie odzwierciedlić mojego SwingWorker. Ale naprawdę nie mogę wymyślić, jak to zrobić. Mam pasek, żeby zrobić statyczną animację, dopóki operacja się nie zakończy, ale chcę mieć aktywny aktywny pasek.SwingWorker ProgressBar

/* 
* To change this template, choose Tools | Templates 
* and open the template in the editor. 
*/ 
package frglauncher; 

import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.RandomAccessFile; 
import java.net.MalformedURLException; 
import java.net.URL; 
import java.nio.channels.Channels; 
import java.nio.channels.ReadableByteChannel; 
import java.util.Enumeration; 
import java.util.jar.JarEntry; 
import java.util.jar.JarFile; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.swing.JLabel; 
import javax.swing.JProgressBar; 
import javax.swing.SwingWorker; 

/** 
* 
* @author KYLE-LAPTOP 
*/ 
class DownloadWorker extends SwingWorker<String, Object> { 

    private String game; 
    private JProgressBar bar; 
    private JLabel label; 

    public DownloadWorker(JProgressBar bar, String game, JLabel label) { 
     this.game = game; 
     this.bar = bar; 
     this.label = label; 
    } 

    @Override 
    public String doInBackground() { 

     // Download here 
     label.setText("test"); 
     try { 
      // ProgressBar/Install 
      System.out.println("FILELOCATION:\n----------"); 
      String URL_LOCATION = "http://www.futureretrogaming.tk/gamefiles/ProfessorPhys.jar"; 
      String LOCAL_FILE = ("\\" + game + "\\"); 
      File localfile = new File(LOCAL_FILE); 
      if (localfile.exists()) { 
       System.out.println("Directory exists!"); 
      } 
      else { 
       System.out.println("Directory doesn't exist! Creating..."); 
       localfile.mkdir(); 
       if (localfile.exists()) { 
        System.out.println("Directory created!"); 
       } 
      } 
      System.out.println("LOCALFILE:\n-------"); 
      System.out.println(LOCAL_FILE); 
      URL website = new URL(URL_LOCATION); 
      ReadableByteChannel rbc = Channels.newChannel(website.openStream()); 
      FileOutputStream fos = new FileOutputStream(LOCAL_FILE + "\\ProfessorPhys.jar\\"); 
      fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 
      System.out.println("--------\nDone Downloading\n---------"); 

      RandomAccessFile randomAccessFile = null; 

      File file = new File(LOCAL_FILE + "ProfessorPhys.jar\\"); 
      JarFile jar = new JarFile(file); 
      Enumeration enum1 = jar.entries(); 
      while (enum1.hasMoreElements()) { 
       JarEntry file1 = (JarEntry) enum1.nextElement(); 
       System.out.println("Directory to extract: " + LOCAL_FILE); 
       System.out.println("\n" + file1.getName() + "\n"); 
       File f = new File(file1.getName()); 
       if (file1.isDirectory()) { // If it's a directory, create it 
        f.mkdir(); 
        continue; 
       } 
       try (InputStream is1 = jar.getInputStream(file1)) { 
        FileOutputStream fos1 = new FileOutputStream(f); 
        while (is1.available() > 0) { // Write contents of 'is' to 'fos' 
         fos1.write(is1.read()); 
        } 
        fos1.close(); 
       } 
      } 
     } 
     catch (FileNotFoundException ex) { 
      Logger.getLogger(DownloadWorker.class.getName()).log(Level.SEVERE, null, ex); 
     } 
     catch (MalformedURLException ex) { 
      Logger.getLogger(DownloadWorker.class.getName()).log(Level.SEVERE, null, ex); 
     } 
     catch (IOException ex) { 
      Logger.getLogger(DownloadWorker.class.getName()).log(Level.SEVERE, null, ex); 
     } 
     return "done"; 
    } 

    @Override 
    protected void done() { 

     // Done 
     label.setText("Download of " + game + "is done."); 
     System.exit(0); 
    } 
} 
+0

Nie zapomnij zaznaczyć wybraną odpowiedź jako zaakceptowany. – Stephan

Odpowiedz

28

Kilka rzeczy:

  1. Istnieją cztery zasady, których należy przestrzegać przy SwingWorker. Możesz odnieść się do tego schematu: enter image description here.

Tak, ten kod:

@Override 
public String doInBackground() { 
    //download here 
    label.setText("test"); 

narusza tę zasadę. Twój label.setText() powinien zostać przeniesiony do konstruktora.

  1. Aby wysłać „aktualizacje” Swing komponentów (jak na pasku postępu) chcesz użyć metody process(), które wywołać korzystając publish() od wewnątrz doInBackground(). Twój parametr odzwierciedla typ wartości, którą chcesz przekazać. Dołączyłem dwa SSCCE. Jedna przechodzi Integer do metody process(), druga przechodzi String. Powinien dać ci wyobrażenie o tym, co się dzieje.

SSCCE użyciu Integer:

import java.util.List; 
import java.util.concurrent.ExecutionException; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JOptionPane; 
import javax.swing.JPanel; 
import javax.swing.JProgressBar; 
import javax.swing.SwingUtilities; 
import javax.swing.SwingWorker; 

/** 
* 
* @author Ryan 
*/ 
public class Test { 

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

    public static void go() { 
     JFrame frame = new JFrame(); 
     JPanel panel = new JPanel(); 
     JLabel label = new JLabel("Loading..."); 
     JProgressBar jpb = new JProgressBar(); 
     jpb.setIndeterminate(false); 
     int max = 1000; 
     jpb.setMaximum(max); 
     panel.add(label); 
     panel.add(jpb); 
     frame.add(panel); 
     frame.pack(); 
     frame.setSize(200,90); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     new Task_IntegerUpdate(jpb, max, label).execute(); 

    } 

    static class Task_IntegerUpdate extends SwingWorker<Void, Integer> { 

     JProgressBar jpb; 
     int max; 
     JLabel label; 
     public Task_IntegerUpdate(JProgressBar jpb, int max, JLabel label) { 
      this.jpb = jpb; 
      this.max = max; 
      this.label = label; 
     } 

     @Override 
     protected void process(List<Integer> chunks) { 
      int i = chunks.get(chunks.size()-1); 
      jpb.setValue(i); // The last value in this array is all we care about. 
      System.out.println(i); 
      label.setText("Loading " + i + " of " + max); 
     } 

     @Override 
     protected Void doInBackground() throws Exception { 
      for(int i = 0; i < max; i++) { 
       Thread.sleep(10); // Illustrating long-running code. 
       publish(i); 
      } 
      return null; 
     } 

     @Override 
     protected void done() { 
      try { 
       get(); 
       JOptionPane.showMessageDialog(jpb.getParent(), "Success", "Success", JOptionPane.INFORMATION_MESSAGE); 
      } catch (ExecutionException | InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

SSCCE użyciu String:

import java.util.List; 
import java.util.concurrent.ExecutionException; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JOptionPane; 
import javax.swing.JPanel; 
import javax.swing.JProgressBar; 
import javax.swing.SwingUtilities; 
import javax.swing.SwingWorker; 

/** 
* 
* @author Ryan 
*/ 
public class Test2 { 

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

    public static void go() { 
     JFrame frame = new JFrame(); 
     JPanel panel = new JPanel(); 
     JLabel label = new JLabel("Loading..."); 
     JProgressBar jpb = new JProgressBar(); 
     jpb.setIndeterminate(true); 
     panel.add(label); 
     panel.add(jpb); 
     frame.add(panel); 
     frame.pack(); 
     frame.setSize(200,90); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     new Task_StringUpdate(label).execute(); 
    } 

    static class Task_StringUpdate extends SwingWorker<Void, String> { 

     JLabel jlabel; 
     public Task_StringUpdate(JLabel jlabel) { 
      this.jlabel = jlabel; 
     } 

     @Override 
     protected void process(List<String> chunks) { 
      jlabel.setText(chunks.get(chunks.size()-1)); // The last value in this array is all we care about. 
      System.out.println(chunks.get(chunks.size()-1)); 
     } 

     @Override 
     protected Void doInBackground() throws Exception { 

      publish("Loading Step 1..."); 
      Thread.sleep(1000); 
      publish("Loading Step 2..."); 
      Thread.sleep(1000); 
      publish("Loading Step 3..."); 
      Thread.sleep(1000); 
      publish("Loading Step 4..."); 
      Thread.sleep(1000); 

      return null; 
     } 

     @Override 
     protected void done() { 
      try { 
       get(); 
       JOptionPane.showMessageDialog(jlabel.getParent(), "Success", "Success", JOptionPane.INFORMATION_MESSAGE); 
      } catch (ExecutionException | InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 
+3

Doskonała odpowiedź, nie tylko z przykładem, ale ze zrozumiałym i poprawnym wyjaśnieniem. Jest lepszy, niż wszystkie samouczki, które widziałem. – Gangnus

+0

To było bardzo pomocne, dziękuję. Jak jednak postępować z raportowaniem postępu doInBackground()? Również narzeka, że ​​@Override jest tam dla funkcji process(). Ale kiedy go usunę, narzeka na funkcję tam. – Kyle

+0

@Kyle, sprawdź, czy parametry typu dla Twojej metody procesu są zgodne z typami 'SwingWorker'. Na przykład, jeśli rozszerzysz 'SwingWorker ', twoja metoda procesu musi zaakceptować 'List ' jako argument. – ryvantage