Java SwingWorker 进度条

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20260372/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 00:38:49  来源:igfitidea点击:

SwingWorker ProgressBar

javaswingfile-ioswingworkerjprogressbar

提问by Kyle

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.

我试图获得一个进度条来准确反映我的 SwingWorker。但我真的不知道该怎么做。我让栏只做一个静态动画,直到操作完成,但我想要一个真正的活动栏。

/*
 * 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);
    }
}

采纳答案by ryvantage

Several things:

几件事:

  1. There are four rules to follow with SwingWorker. You can refer to this diagram: enter image description here.
  1. 有四个规则要遵循SwingWorker。可以参考这张图:在此处输入图片说明

So, this code:

所以,这段代码:

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

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

违反了该规则。你label.setText()应该被移动到构造函数。

  1. 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 secondSwingWorkerparameter reflects the type of value you want to pass. I've attached two SSCCEs. One passes an Integerto the process()method, the other passes a String. Should give you an idea of what's going on.
  1. 要将“更新”发送到 Swing 组件(如进度条),您需要process()使用publish()doInBackground(). 您的第二个SwingWorker参数反映了您要传递的值的类型。我附上了两个 SSCCE。一个传递Integerprocess()方法,另一个传递一个String。应该让你知道发生了什么。

SSCCE using Integer:

SSCCE 使用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:

SSCCE 使用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();
            }
        }
    }
}