JProgressBar from Oracle

时光毁灭记忆、已成空白 提交于 2019-12-25 19:03:46

问题


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!\n");
    }
}

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.\n", 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();
        }
    });
}
}

回答1:


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)



来源:https://stackoverflow.com/questions/54012205/jprogressbar-from-oracle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!