Java更新进度条

5

我有一个JFrame和以下组件。

JButton = jButton1 进度条 = progressBar和它的public static JLabel = status和它的public static

当按钮被点击时,不同的语句会执行。我想在每个语句之后更新我的进度条。这是我的代码:

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

这是我的任务类,使用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;
    }

}

有什么办法可以解决这个问题吗?
2个回答

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

您不希望在Swing线程之外更新GUI组件。 SwingWorker 提供了钩子来在事件分派线程上执行操作,这就是它的设计目的。从doInBackground调用publish方法,并覆盖process以处理增量更新。或者,如果只需要在完成时更新GUI,则覆盖done()方法。
一个非常简单的示例:
//...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);
    }
}

编辑

@mKorbel指出了一个很好的观点,为了使上述内容起作用,需要扩展SwingWorker<Void,Integer>... Void是整个返回值类型(在这种情况下表示没有返回值),而Integer是增量更新的类型。

如果worker生成实际的最终结果(将使用get()检索该结果),则可以在Void的位置使用该类型。我省略了这些详细信息,因为我没有包括类声明。

查看


1
请修改您的答案,并添加(这并不是 OP 的问题),SwingWorker 必须声明为 SwingWorker<T,V>,而不是普通的 vanilla。OP 声明了 'public class Task extends SwingWorker{..}'。 - mKorbel
@mKorbel 提出了一个很好的观点。SwingWorker 的通用参数值得一试。这里有相关的示例链接,也可以在 API 中找到。 - trashgod
@mKorbel,@trashgod:谢谢,我已经更新了我的答案并明确说明了。 - Mark Peters
关于@trashgod的链接,它展示了一种更直接的方式来特定地创建一个进度条,其值为0-100。因此,我的示例有点牵强,因为有明确支持基于百分比的进度更新。 - Mark Peters

2
除了Mark的回答之外,你真的不想在actionPerformed()方法中睡觉。如果与GUI组件链接,此方法由AWT / Swing事件分派线程调用,该线程还执行绘画和其他操作。只要您的方法未完成,您的GUI将被阻止。
请在SwingWorker或另一个线程中等待所有内容。

+1 确切无误;这个示例在后台线程中休眠以模拟延迟。 - trashgod

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接