从单独的类更新JProgressBar

时间:2013-12-27 23:52:08

标签: java swing class external updateprogress

我一直在关注这个帖子,尝试从我的程序中的一个单独的类更新JProgressBar:java - Progress Bar - Is it possible to use setProgess() of Progress Bar outside the doInBackground() method?

不幸的是我的代码无法正常工作。我可能错过了什么,但我似乎无法弄清楚它是什么。这是我到目前为止编写的代码:

这是我用来更新进度条的propertyChangeListener:

PropertyChangeListener listener = new PropertyChangeListener(){
        public void propertyChange(PropertyChangeEvent event){
            if("progress".equals(event.getPropertyName())){
                progressBar.setValue((int)currentPercent);
                progressBar.setString(Integer.toString((int)currentPercent));
            }
        }
    };

SwingWorker类:​​

class Task extends SwingWorker<Void, String>{

    public Task(){
        md = new ManipulateDirectories(this);
    }
    @Override
    public Void doInBackground(){
        for(int i = 0; i < directories.length; i++){
            md.copyDirectory(directories[i], backupDir);
        }
        return null;
    }

    @Override
    public void process(List<String> chunks){
    }

    @Override
    public void done(){
        closeWindow();
    }

    public void updateProgress(int tick){
        setProgress(tick);
    }
}

ManipulateDirectories类:

public class ManipulateDirectories{
    Task task;
    public ManipulateDirectories(Task task){
        this.task = task;
    }

    //Recursive function to loop through and copy individual files
    public void copyDirectory(File file, File dest){
        if(file.isFile()){
            try {
                FileUtils.copyFileToDirectory(file, dest);
                currentSize = currentSize + getDirSize(file);
                if(currentSize >= ONE_PERCENT){
                    currentPercent = currentPercent + (currentSize / ONE_PERCENT);
                    task.updateProgress((int)currentPercent); //THIS LINE DOES NOT WORK
                    currentSize = currentSize % ONE_PERCENT;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else if (file.isDirectory()){
            File newDir = new File(String.format("%s\\%s", dest.getAbsolutePath(), file.getName()));
            if(!newDir.exists()){
                newDir.mkdir();
                for(File f : file.listFiles()){
                    copyDirectory(f, newDir);
                }
            }
        }
    }

    public Long getDirSize(File file) {
        long size = 0L;

        if (file.isFile() && file != null){       
            size += file.isDirectory() ? getDirSize(file) : file.length();
        } else if (file.isDirectory()){
            for (File f : file.listFiles()) {
                size += f.isDirectory() ? getDirSize(f) : file.length();
            }
        }
        return size;

    }
}

正如您所看到的,propertyChangeListener应该由swingworker类中的updateProgress(int)方法触发,并且该方法应该由ManipulateDirector类中的行task.updateProgress((int)currentPercent)调用。但是,该行似乎没有调用updateProgress()。我猜它可能是“任务”的特定实例的问题 - 也许我正在创建一个没有正确上下文的单独实例? (我知道术语可能有点不对,但希望你能理解我想说的话)。谁能发现我的错误?任何帮助都会非常感激,我已经坚持了很长一段时间了。

SSCCE:

import java.awt.BorderLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import javax.swing.border.EmptyBorder;

public class MainClass extends JFrame {
    private JProgressBar progressBar;
    private DoSomething ds;
    private int currentPercent = 0;
    private Task task;
    private static JPanel contentPane;
    private JPanel bottomPane;
    private JButton btnCancel;

    public static void main(String[] args){
        MainClass mc = new MainClass();
        mc.createGUI();
    }
    public void createGUI(){
        //Create frame
        setTitle("Backup Progress");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 350);
        //Create content pane
        contentPane = new JPanel(new BorderLayout());
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        //Create panel for progress bar/cancel button
        bottomPane = new JPanel();
        bottomPane.setLayout(new BoxLayout(bottomPane, BoxLayout.Y_AXIS));

        progressBar = new JProgressBar(0, 100);
        progressBar.setStringPainted(true);
        progressBar.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        progressBar.setValue(0);

        btnCancel = new JButton("Cancel");
        btnCancel.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                closeWindow();
            }
        });

        bottomPane.add(progressBar);
        bottomPane.add(btnCancel);
        contentPane.add(bottomPane, BorderLayout.SOUTH);

        PropertyChangeListener listener = new PropertyChangeListener(){
            public void propertyChange(PropertyChangeEvent event){
                if("progress".equals(event.getPropertyName())){
                    progressBar.setValue((int)currentPercent);
                    progressBar.setString(Integer.toString((int)currentPercent));
                }
            }
        };

        setVisible(true);
        task = new Task();
        task.execute();
    }

    class Task extends SwingWorker<Void, String>{
        public Task(){
            ds = new DoSomething(this);
        }
        @Override
        public Void doInBackground(){
            for(int i = 0; i < 100; i++){
                ds.incrementPercent();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }
        @Override
        public void done(){
            closeWindow();
        }
        public void updateProgress(int tick){
            setProgress(currentPercent + tick);
        }
    }

    public class DoSomething{
        Task task;
        public DoSomething(Task task){
            this.task = task;
        }
        public void incrementPercent(){
            task.updateProgress(1);
        }
    }

    public void closeWindow(){
        WindowEvent close = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
        Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(close);
    }
} 

我意识到这是一个非常长的SSCCE,但希望它能为您提供您需要知道的所有信息。

1 个答案:

答案 0 :(得分:3)

您永远不会将您的听众添加到SwingWorker

更改为:

task = new Task();
task.addPropertyChangeListener(listener);

您遇到的另一个错误是您永远不会更新currentPercent中的updateProgress

public void updateProgress(int tick){
            currentPercent+=tick;
            setProgress(currentPercent);
}

修改

实际上,您的错误在您的代码(而不是sscce)中是相同的,您永远不会更新currentPercent值。

PropertyChangeListener listener = new PropertyChangeListener(){
            public void propertyChange(PropertyChangeEvent event){
                if("progress".equals(event.getPropertyName())){
                    currentPercent = (int)event.getNewValue();
                    progressBar.setValue(currentPercent);
                    progressBar.setString(Integer.toString(currentPercent));
                }
            }
        };