【问题标题】:thread in Java Swing don't workJava Swing中的线程不起作用
【发布时间】:2013-10-04 19:29:22
【问题描述】:

我有一些带有for 循环的简单代码。在循环的每一次通过中,我都必须增加 JProgressBar;但是,这不起作用。见下文:

public void atualizarBarraDeProgresso(final int valorGeral, final int valorAtual) {
    Thread threadProgressoCarregamento = new Thread() {
        @Override
        public void run() {
             jProgressBarPersistindo.setValue(valorAtual);
        }
    };
    threadProgressoCarregamento.start();
}

我在如下循环中调用方法“atualizarBarraDeProgresso”:

progressBar.setMinimum(0);
progressBar.setMaximum(qtd);
for(int i = 0; i < qtd; i++) { 
    atualizarBarraDeProgresso(qtd, i + 1);
    doSomething();
}

但是我的进度条没有任何反应。

【问题讨论】:

  • 真的想要那么多线程吗?无论如何,我怀疑问题在于 循环本身 发生在 ADT 上(即在“点击处理程序”中)并且 阻塞 Swing UI 交互和更新直到它完成.考虑使用SwingWorker - 正确使用可能会消除所有问题。此外,请确保更新 ADT 上的 Swing 对象。
  • 在任何时候设置值后,您是否在包含的 JPanel 上调用 repaint()?这可能就是缺少的一切。
  • 调用repaint()方法,顺便说一下,解决方法很糟糕。
  • @user2246674(礼貌的咳嗽)由'ADT'DYM'EDT'?对于OP,一般提示。不要阻塞 EDT(事件调度线程)——当这种情况发生时,GUI 将“冻结”。而不是调用Thread.sleep(n) 实现一个Swing Timer 用于重复任务或SwingWorker 用于长时间运行的任务。有关详细信息,请参阅Concurrency in Swing
  • 这是所需逻辑的一个有趣的反转:此代码确保修改是唯一的操作 不是 i> 在美国东部时间。

标签: java multithreading swing event-dispatch-thread jprogressbar


【解决方案1】:

尝试在 for 语句之前添加一个线程。我希望它有效

    progressBar.setMinimum(0);
    progressBar.setMaximum(qtd);

    new Thread(){
        @Override
        public void run() {
            for(int i = 0; i < qtd; i++) { 
                atualizarBarraDeProgresso(qtd, i + 1);
                doSomething();
            }
        }
    }.start();

【讨论】:

    【解决方案2】:

    这应该可以通过SwingWorker 实现轻松管理。 SwingWorkers 当您需要“做某事”但又不想在做时阻止 GUI 时很有用。当您需要更新 GUI 组件同时通过 publish()/process() 方法进行其他工作时,该类还为您提供了一个有用的 API,用于与 EDT 进行通信。

    以下实现在工作线程上处理您的循环,以便它不会阻塞 EDT(GUI 线程)。对 publish(Integer...) 的调用将作为对 process(List) 的调用转发到 EDT,这是您要更新 JProgressBar 的地方,因为与所有 Swing 组件一样,您应该只在 EDT 上更新 JProgressBar。

    public class MySwingWorker extends SwingWorker<Void, Integer> {
    
        private final int qtd;
        private final JProgressBar progressBar;
    
        public MySwingWorker(JProgressBar progressBar, int qtd){
            this.qtd = qtd;
            this.progressBar = progressBar;
        }
    
        /* This method is called off the EDT so it doesn't block the GUI. */
        @Override
        protected Void doInBackground() throws Exception {
            for(int i = 0; i < qtd; i++) { 
    
                /* This sends the arguments to the process(List) method 
                 * so they can be handled on the EDT. */
                publish(i + 1);
    
                /* Do your stuff. */
                doSomething();
            }
            return null;
        }
    
        /* This method is called on the EDT in response to a 
         * call to publish(Integer...) */
        @Override
        protected void process(List<Integer> chunks) {
            progressBar.setValue(chunks.get(chunks.size() - 1));
        }
    }
    

    你可以这样开始

    int qtd = ...;
    
    progressBar.setMinimum(0);
    progressBar.setMaximum(qtd);
    
    SwingWorker<? ,?> worker = new MySwingWorker(progressBar, qtd);
    
    worker.execute();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-06
      • 2014-06-17
      • 1970-01-01
      • 1970-01-01
      • 2011-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多