SwingWorker ProgressBar

file-io, java, jprogressbar, swing, swingworker

Solution

Several things:

- There are four rules to follow with `SwingWorker`. You can refer to this diagram: .

So, this code:

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

violates that rule. Your `label.setText()` should be moved to the constructor.

- To send "updates" to Swing components (like your progress bar) you want to use the `process()` method, which you invoke using `publish()` from inside your `doInBackground()`. Your second `SwingWorker` parameter reflects the type of value you want to pass. I've attached two SSCCEs. One passes an `Integer` to the `process()` method, the other passes a `String`. Should give you an idea of what's going on.

SSCCE using `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 using `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();
            }
        }
    }
}

Problem

I am trying to get a progress bar to accurately reflect my SwingWorker. But I really can't figure out how to do it. I got the bar to just do a static animation until the operation has completed but I want a real active bar. ``` /* * 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); } } ```

Original source