2

如何从另一个线程更新 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。

4

3 回答 3

3

始终遵守摇摆规则

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

您可以做的是创建一个观察者来更新您的进度条 - 例如 - 在这种情况下,您希望显示单击按钮时正在加载的数据的进度。 DemoHelperObservable在加载一定百分比的数据时实现并向所有观察者发送更新。进度条通过以下方式更新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());
    }
}

无耻插件:这是来自我的演示项目的源代码 随意浏览以获取更多详细信息。

于 2010-04-28T00:41:51.840 回答
0

你不应该在事件调度线程之外做任何 Swing 的事情。要访问它,您需要使用运行中的代码创建一个 Runnable,然后将其传递给 SwingUtilities.invokeNow() 或 SwingUtilities.invokeLater()。问题是我们需要延迟 JProgressBar 检查以避免阻塞 Swing 线程。为此,我们需要一个 Timer,它会在自己的 Runnable 中调用 invokeNow 或稍后。查看http://www.javapractices.com/topic/TopicAction.do?Id=160了解更多详情。

于 2010-04-28T00:35:18.860 回答
0
  • 不需要显式调用 pbra.repaint。
  • 更新 JProgressBar 应通过 GUI 调度线程完成。

SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        // Remember to make pbar final variable.
        pbar.setValue(i);
    }
});
于 2010-04-28T00:35:50.167 回答