如何从Thread更新java GUI?

时间:2012-11-24 16:56:33

标签: java swing

 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,所以我该怎么办?

2 个答案:

答案 0 :(得分:6)

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

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

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

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

代码行

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

Workers Thread通过defaut永远不会调用EDT,然后从EDT开始并不重要,也不测试isDispatchThread()不会让我有所作为

    永远不要在Thread.sleep(int内使用Swing Listeners),因为也导致了Swing GUI的冻结

  • 我认为您也可以使用SwingWorker for this job

答案 1 :(得分:5)

我认为你必须将整个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();