2013-11-28 14 views
9

Sto cercando di ottenere una barra di avanzamento per riflettere con precisione il mio SwingWorker. Ma davvero non riesco a capire come farlo. Ho ottenuto la barra per fare solo un'animazione statica fino al completamento dell'operazione, ma voglio una vera barra attiva.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

Non dimenticate di segnare la risposta scelta come accettata. – Stephan

risposta

28

diverse cose:

  1. Ci sono quattro regole da seguire con SwingWorker. È possibile fare riferimento a questo diagramma: enter image description here.

Quindi, questo codice:

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

viola questa regola. Il tuo label.setText() dovrebbe essere spostato nel costruttore.

  1. Per inviare "aggiornamenti" a Swing componenti (come la vostra barra di avanzamento) che si desidera utilizzare il metodo process(), che si richiama utilizzando publish() da dentro il doInBackground(). Il tuo secondoSwingWorker parametro riflette il tipo di valore che si desidera passare. Ho allegato due SSCCE. Si passa un Integer al metodo process(), l'altro passa a String. Dovresti darti un'idea di cosa sta succedendo.

SSCCE utilizzando 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 utilizzando 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

Ottima risposta, non solo con un esempio, ma con spiegazione comprensibile e corretta. È meglio di tutti i tutorial che ho visto. – Gangnus

+0

Questo è stato piuttosto utile grazie. Come faccio a segnalare i progressi del doInBackground()? Inoltre continua a lamentarsi che @Override è lì per la funzione process(). Ma quando lo rimuovo, si lamenta della funzione lì. – Kyle

+0

@Kyle, verificare che i parametri del tipo per il metodo di elaborazione corrispondano ai tipi 'SwingWorker'. Ad esempio, se estendi "SwingWorker ", il tuo metodo di processo deve accettare un 'List ' come argomento. – ryvantage