开发者

java update progressbar

开发者 https://www.devze.com 2023-03-11 06:25 出处:网络
I have a JFrame and following components. JButton = jButton1 Progress Bar = progressBar and its public static

I have a JFrame and following components.

JButton = jButton1 Progress Bar = progressBar and its public static 开发者_运维知识库JLabel = status and its public static

When button clicks then different statements execute. I want to update my progressbar after each statement. Here is my code

   private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        Task pbu = new Task(25, "Step 1....");
        pbu.execute();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }

        pbu = new Task(50, "Step 2....");
        pbu.execute();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }

        pbu = new Task(75, "Step 3....");
        pbu.execute();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }

        pbu = new Task(100, "Done");
        pbu.execute();
    }

Here is my Task Class extended with SwingWorker

public class Task extends SwingWorker{

    private int progress;
    private String stat;

    public Task(int pr, String st) {
        progress = pr;
        stat = st;
    }

    @Override
    protected Object doInBackground() throws Exception {
        NewJFrame1.progressBar.setValue(progress);
        NewJFrame1.status.setValue(stat);
        return null;
    }

}

Any idea how can I solve this problem?


   @Override
    protected Object doInBackground() throws Exception {
        NewJFrame1.progressBar.setValue(progress);
        NewJFrame1.status.setValue(stat);
        return null;
    }

You don't want to update GUI components off of the Swing thread. SwingWorker provides hooks for doing stuff back on the Event Dispatch Thread, that's what it's designed for. Call the publish method from doInBackground and override process to detail with incremental updates. Or, if you only need to update the GUI when it's finished, override the done() method.

A very simple example:

//...in some concrete implementation of SwingWorker<Void, Integer>
protected Void doInBackground() throws Exception {
    //do 10% of task
    doLongOp();
    publish(10);

    //do another 20% of task
    doAnotherLongOp();
    publish(20);

    return null;
}

protected void process(List<Integer> pieces) {
    for (Integer percent : pieces ) {
       progressBar.setValue(progressBar.getValue() + percent);
    }
}

Edit

@mKorbel makes a good point that for the above to work it needs to extend SwingWorker<Void, Integer>...Void being the overall return value type (in this case indicating there's no return value) and Integer being the type of the incremental updates.

If the worker produces an actual final result (that will be retrieved with get()) then that type can be used in place of Void. I had left out these details since I didn't include the class declaration.

See

  • SwingWorker


In addition to the answer from Mark, you really don't want to sleep in the actionPerformed() method. This method is (if linked to a GUI component) called by the AWT/Swing event dispatch thread, the same thread that also does painting and everything. As long as your method is not finished, your GUI will be blocked.

Do all your waiting in a SwingWorker or another thread.

0

精彩评论

暂无评论...
验证码 换一张
取 消