【问题标题】:Update JProgressBar from new Thread从新线程更新 JProgressBar
【发布时间】:2010-04-28 00:31:03
【问题描述】:

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

【问题讨论】:

    标签: java multithreading jprogressbar


    【解决方案1】:

    始终遵守摇摆规则

    一旦实现了 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 欢迎浏览以了解更多详情。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:
        • 不需要显式调用 pbra.repaint。
        • 更新 JProgressBar 应通过 GUI 调度线程完成。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-11-07
          • 1970-01-01
          • 2020-12-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多