Using SwingWorker to update the progress of a thre

2019-06-14 02:40发布

问题:

Value is updated by the end, but not during the process. I guess the reason is that the publish method locates outside the loop.

As to invoke PropertyChangeListener, can it be achieved by defining the class without extends SwingWorker<Void, Void> ?

To address the question in another way, I have two threads locate in two different classes. Is it possible to build communication between the two using SwingWorker?

Class Application

import javax.swing.JFrame;

public class Application {
    public static void main(String[] args){
        javax.swing.SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run() {
                JFrame frame = new Progress();
                frame.setSize(200, 300);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.pack();
                frame.setVisible(true);
            }
        });     
    }
}

Class Progress

import java.awt.BorderLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;

@SuppressWarnings("serial")
public class Progress extends JFrame{
    private JProgressBar progressbar;

    public Progress(){
        JButton button = new JButton("Run");
        progressbar = new JProgressBar(0, 100);
        progressbar.setValue(0);
        progressbar.setStringPainted(true);
        JPanel panel = new JPanel();
        panel.add(button);
        panel.add(progressbar);
        add(panel, BorderLayout.PAGE_START);

        button.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent event){
                start();
            }
        });
    }

    private void start(){
        progressbar.setValue(0);

        SwingWorker<Void, Integer> worker = new SwingWorker<Void, Integer>(){

            @Override
            protected Void doInBackground() throws Exception {
                Simulation sim = new Simulation();
                publish(sim.getCount());
                return null;
        }

            @Override
            protected void process(List<Integer> chunks) {
                Integer progress = chunks.get(chunks.size()-1);
                progressbar.setValue(progress);
                progressbar.repaint();
                progressbar.update(progressbar.getGraphics());
            }

            @Override
            protected void done() {
                Toolkit.getDefaultToolkit().beep();
            }
        };
        worker.execute();
    }
}

Class Simulation

public class Simulation {
    private int count;

    public Simulation(){
        for(int i=0; i<100; i++){
            count++;
            System.out.println(count);

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public int getCount(){
        return count;
    }
}

How can I update the value during the process?

回答1:

You need to implement PropertyChangeListener on your SwingWorker and listen to the Progress property changes and then from overridden propertChange() method update your JProgressBar.

Here is what you are looking.

Hope this helps.