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