如何从Thread更新java GUI?

private void StartActionPerformed(java.awt.event.ActionEvent evt) { Queue queue=new Queue(); int target=Integer.parseInt(Target.getText()); String path=Path.getText(); final Producer p=new Producer(queue, target); Consumer c=new Consumer(queue); p.start(); c.start(); while(p.finish !=true) { Runnable r = new Runnable() { public void run() { ProgressPrecent.setValue(Producer.ProgressPercent); } }; if(EventQueue.isDispatchThread()) { r.run(); } else { EventQueue.invokeLater(r); } } } 

我有两个具有共享队列的类。 其中一个是Producer,它生成直到一个目标,另一个消耗这些元素。 所有两个都扩展了Thread。 我想向用户显示进度百分比,但它会冻结我的GUI,所以我该怎么办?

  • 默认情况下, Worker Threads永远不会调用EventDispatchThread ,你Concurency in Swing遇到Concurency in Swing问题

  • Swing GUI的所有更新必须在EDT上完成

  • Runnable可能是正确的方法,但ProgressPrecent.setValue(Producer.ProgressPercent); 必须包装在invokeLater

 SwingUtilities.invokeLater(new Runnable(){ public void run(){ ProgressPrecent.setValue(Producer.ProgressPercent); } }); 
  • 删除EDT测试,

代码行

 if(EventQueue.isDispatchThread()) { r.run(); } 

通过defaut Workers Thread永远不会调用EDT,然后从EDT启动无关紧要,也不测试isDispatchThread()不会让我有所作为

  • 从来没有,不要在Swing Listeners使用Thread.sleep(int ),因为它也导致了Swing GUI的冻结

  • 我想你也可以使用SwingWorker来完成这项工作

我认为你必须把整个while循环放到一个线程中。 否则循环将阻止您的ActionEvent,从而冻结UI。

就像是:

 new Thread(){ public void run(){ while(!p.finish){ SwingUtilities.invokeLater(new Runnable(){ public void run(){ ProgressPrecent.setValue(Producer.ProgressPercent); } }); try{ Thread.sleep(100); }catch(...){} } } }.start();