Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I've downloaded a small Java project from oracle website to create a progress bar.

I understand it, but I need to apply it in a different way, the application is creating a thread in the background so the progress bar can be updated accordingly (doInBackground()).

My question is, how can I replace this kind of process in the background in this application by a method from my application (method is just doing a kind of batch processing on a database), can someone help please?

Here is code by Oracle:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.beans.*; 
import java.util.Random;


public class ProgressBarDemo2 extends JPanel
       implements ActionListener, PropertyChangeListener {

private JProgressBar progressBar;
private JButton startButton;
private JTextArea taskOutput;
private Task task;

class Task extends SwingWorker<Void, Void> {
    /*
     * Main task. Executed in background thread.
     */
    @Override
    public Void doInBackground() {
        Random random = new Random();
        int progress = 0;
        //Initialize progress property.
        setProgress(0);
        //Sleep for at least one second to simulate "startup".
        try {
            Thread.sleep(1000 + random.nextInt(2000));
        } catch (InterruptedException ignore) {}
        while (progress < 100) {
            //Sleep for up to one second.
            try {
                Thread.sleep(random.nextInt(1000));
            } catch (InterruptedException ignore) {}
            //Make random progress.
            progress += random.nextInt(10);
            setProgress(Math.min(progress, 100));
        }
        return null;
    }

    /*
     * Executed in event dispatch thread
     */
    public void done() {
        Toolkit.getDefaultToolkit().beep();
        startButton.setEnabled(true);
        taskOutput.append("Done!
");
    }
}

public ProgressBarDemo2() {
    super(new BorderLayout());

    //Create the demo's UI.
    startButton = new JButton("Start");
    startButton.setActionCommand("start");
    startButton.addActionListener(this);

    progressBar = new JProgressBar(0, 100);
    progressBar.setValue(0);

    //Call setStringPainted now so that the progress bar height
    //stays the same whether or not the string is shown.
    progressBar.setStringPainted(true); 

    taskOutput = new JTextArea(5, 20);
    taskOutput.setMargin(new Insets(5,5,5,5));
    taskOutput.setEditable(false);

    JPanel panel = new JPanel();
    panel.add(startButton);
    panel.add(progressBar);

    add(panel, BorderLayout.PAGE_START);
    add(new JScrollPane(taskOutput), BorderLayout.CENTER);
    setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
}

/**
 * Invoked when the user presses the start button.
 */
public void actionPerformed(ActionEvent evt) {
    progressBar.setIndeterminate(true);
    startButton.setEnabled(false);
    //Instances of javax.swing.SwingWorker are not reusuable, so
    //we create new instances as needed.
    task = new Task();
    task.addPropertyChangeListener(this);
    task.execute();
}

/**
 * Invoked when task's progress property changes.
 */
public void propertyChange(PropertyChangeEvent evt) {
    if ("progress" == evt.getPropertyName()) {
        int progress = (Integer) evt.getNewValue();
        progressBar.setIndeterminate(false);
        progressBar.setValue(progress);
        taskOutput.append(String.format(
                    "Completed %d%% of task.
", progress));
    }
}

/**
 * Create the GUI and show it. As with all GUI code, this must run
 * on the event-dispatching thread.
 */
private static void createAndShowGUI() {
    //Create and set up the window.
    JFrame frame = new JFrame("ProgressBarDemo2");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    //Create and set up the content pane.
    JComponent newContentPane = new ProgressBarDemo2();
    newContentPane.setOpaque(true); //content panes must be opaque
    frame.setContentPane(newContentPane);

    //Display the window.
    frame.pack();
    frame.setVisible(true);
}

public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application's GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI();
        }
    });
}
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
125 views
Welcome To Ask or Share your Answers For Others

1 Answer

First, I'd recommend by defining a concept of a "progressable" state

public interface Progressable {
    public void setProgress(int progress); // I prefer double, but we'll keep it inline with the rest of the API
}

Then, the entry point for your tasks would take a reference to Progressable

public class MySuperAwesomeLongRunningTask ... {
    //...
    private Progressable progressable;

    public void performTask(Progressable progressable) {
        this.prgressable = progressable
    }

    protected void methodThatDoesSomeWork() {
        // Do some super duper work...
        // calculate the progress of that work some how,
        // based on your implementation...
        int progress = ...;
        progressable.setProgress(progress);
    }
}

Then, create a SwingWorker which implements Progressable and calls your work...

class Task extends SwingWorker<Void, Void> implements Progressable {
    private MySuperAwesomeLongRunningTask taskToBeDone;

    public Task(MySuperAwesomeLongRunningTask taskToBeDone) {
        self.taskToBeDone = taskToBeDone;
    }

    /*
     * Main task. Executed in background thread.
     */
    @Override
    public Void doInBackground() {
        taskToBeDone.performTask(this);
        return null;
    }

    /*
     * Executed in event dispatch thread
     */
    public void done() {
        // What ever you need to do...
    }
}

Now, because SwingWorker already has a method called setProgress(int) it automatically conforms to Progressable (so long as you implement it), so when MySuperAwesomeLongRunningTask calls setProgress, it will actually be calling the SwingWorkers implementation.

This means, that the rest of the code basically remains the same, expect, I'd change

if ("progress" == evt.getPropertyName()) {

to

if ("progress".equals(evt.getPropertyName())) {

because comparing Strings with == is bad idea (and freaks me out :P)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...