Question

I've been following this thread to try to update a JProgressBar from a separate class in my program: java - Progress Bar - Is it possible to use setProgess() of Progress Bar outside the doInBackground() method?

Unfortunately my code isn't work properly. I probably missed something, but I can't seem to figure out what it was. This is the code I have written so far:

Here is the propertyChangeListener I use to update the progress bar:

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:

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 class:

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;

    }
}

As you can see, the propertyChangeListener should be fired by the updateProgress(int) method within the swingworker class, and that method should be called by the line: task.updateProgress((int)currentPercent) which is in the ManipulateDirectories class. However, that line does not seem to call updateProgress(). I am guessing it might be a problem with the particular instance of "Task"--perhaps I am creating a separate instance that does not have the correct context? (I know the terminology is probably a bit wrong, but hopefully you can understand what I'm trying to say). Can anyone spot my mistake/s? Any help would be very much appreciated, I've been stuck on this for quite a while now.

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

I realize that's a very long SSCCE, but hopefully it gives you all the information you need to know.

Was it helpful?

Solution

You never add your listener to your SwingWorker.

Change to:

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

The other error you have is that you never update your currentPercent in updateProgress.

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

EDIT

Well and actually your error is the same in your code (not sscce), you never update your currentPercent value.

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));
                }
            }
        };
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top