从新线程更新JProgressBar

时间:2010-04-28 00:31:03

标签: java multithreading jprogressbar

如何从另一个线程更新JProgressBar.setValue(int)? 我的第二个目标是在尽可能少的课程中完成。

以下是我现在的代码:

// Part of the main class....
pp.addActionListener(
        new ActionListener(){
            public void actionPerformed(ActionEvent event){
                new Thread(new Task(sd.getValue())).start(); 
            }
        });

public class Task implements Runnable {
    int val;
    public Task(int value){
        this.val = value;
    }

    @Override
    public void run() {
        for (int i = 0; i <= value; i++){ // Progressively increment variable i 
            pbar.setValue(i); // Set value 
            pbar.repaint(); // Refresh graphics 
            try{Thread.sleep(50);} // Sleep 50 milliseconds 
            catch (InterruptedException err){} 
        } 
    }
}

pp是一个JButton,并在单击JButton时启动新线程。

pbar是Main类中的JProgressBar对象。

如何更新其价值?(进度)

run()中的代码无法看到pbar。

3 个答案:

答案 0 :(得分:3)

始终遵守挥杆规则

一旦实现了Swing组件,所有可能影响或依赖于该组件状态的代码都应该在事件派发线程中执行。

你可以做的是创建一个会更新进度条的观察者 - 例如 - 在这种情况下,您希望显示单击按钮时加载的数据的进度。 DemoHelper类实现Observable并在加载某些百分比数据时向所有观察者发送更新。 进度条通过public void update(Observable o, Object arg) {

更新
class PopulateAction implements ActionListener, Observer {

    JTable tableToRefresh;
    JProgressBar progressBar;
    JButton sourceButton;
    DemoHelper helper;
    public PopulateAction(JTable tableToRefresh, JProgressBar progressBarToUpdate) {
        this.tableToRefresh = tableToRefresh;
        this.progressBar = progressBarToUpdate;
    }

    public void actionPerformed(ActionEvent e) {
        helper = DemoHelper.getDemoHelper();
        helper.addObserver(this);
        sourceButton = ((JButton) e.getSource());
        sourceButton.setEnabled(false);
        helper.insertData();
    }

    public void update(Observable o, Object arg) {
        progressBar.setValue(helper.getPercentage());
    }
}

无耻插件:来自source from my demo project 随意浏览更多详细信息。

答案 1 :(得分:0)

您不应该在事件派发线程之外执行任何Swing操作。要访问它,您需要使用运行中的代码创建一个Runnable,然后将其传递给SwingUtilities.invokeNow()或SwingUtilities.invokeLater()。问题是我们需要延迟你的JProgressBar检查以避免干扰Swing线程。为此,我们需要一个Timer,它将在自己的Runnable中调用invokeNow或更高版本。有关详细信息,请查看http://www.javapractices.com/topic/TopicAction.do?Id=160

答案 2 :(得分:0)

  • 无需明确调用pbra.repaint。
  • 更新JProgressBar应通过GUI分派线程完成。

SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        // Remember to make pbar final variable.
        pbar.setValue(i);
    }
});