2012-05-05 92 views
0

我正在编写一个应用程序,它可以进行一些音频分析(用作吉他调谐器,还有和弦估计以及其他一些东西),但是我在GUI上遇到了一些麻烦。第一个问题是我有一个按钮,点击后应该改变其显示的文字。当它被点击时,文本不会改变,但是应该改变它的代码行肯定是可以达到的。重复执行SwingWorker

另一件事是我需要一个SwingWorker重复执行(一旦完成后重新启动)并每次更新GUI。由于目前我的代码,我有一个while循环反复执行我的SwingWorker,但这导致GUI由于它在EDT中运行(假定)而变得无响应。让SwingWorker重复执行的最佳方式是什么?我应该只是创建一个新的线程来运行循环,或其他?

代码为我的内心的ActionListener类如下:

private class TunerListener implements ActionListener { 
    private boolean firstUpdate = true; 
    private volatile boolean executing = false; 

    private final SwingWorker<Void, Void> tunerWorker = new SwingWorker<Void, Void>() { 

     @Override 
     protected Void doInBackground() { 
      model.update(); 
      return null; 
     } 

     @Override 
     protected void done() { 
      if (!this.isCancelled()) { 
       prev.setText(model.getPrev()); 
       currentNote.setText(model.getNote()); 
       next.setText(model.getNext()); 
       frequency.setText(model.getFrequency()); 
       switch (model.getOffset()) { 
        case -2: 
         light_2.setIcon(onRed); 
         light_1.setIcon(off); 
         light0.setIcon(offBig); 
         light1.setIcon(off); 
         light2.setIcon(off); 
         break; 
        case -1: 
         light_2.setIcon(off); 
         light_1.setIcon(onRed); 
         light0.setIcon(offBig); 
         light1.setIcon(off); 
         light2.setIcon(off); 
         break; 
        case 0: 
         light_2.setIcon(off); 
         light_1.setIcon(off); 
         light0.setIcon(onGreen); 
         light1.setIcon(off); 
         light2.setIcon(off); 
         break; 
        case 1: 
         light_2.setIcon(off); 
         light_1.setIcon(off); 
         light0.setIcon(offBig); 
         light1.setIcon(onRed); 
         light2.setIcon(off); 
         break; 
        case 2: 
         light_2.setIcon(off); 
         light_1.setIcon(off); 
         light0.setIcon(offBig); 
         light1.setIcon(off); 
         light2.setIcon(onRed); 
         break; 
       } 
      } 
     } 

    }; 

    @Override 
    public void actionPerformed(ActionEvent ae) { 

     if (ae.getActionCommand().equals("tune")) { 
      if (!executing) { 
       tune.setText("Stop Tuning"); 
       executing = true; 

       while (executing) { 
        tunerWorker.execute(); 
        firstUpdate = false; 
       } 
       firstUpdate = true; 
      } else { 
       tune.setText("Start Tuning"); 
       executing = false; 
       tunerWorker.cancel(true); 
       firstUpdate = true; 
      } 
     } 

    } 
} 

编辑:按钮上的文字问题似乎已经被固定现在,但我仍然不能得到这个SwingWorker的正常工作。我已经尝试完全删除while循环,并让它从其done()方法重新执行本身,但这似乎并不能帮助您处理...

+2

通常最好为每个问题提出一个单独的问题 – Tharwen

+0

但是......在这种情况下,似乎问题是相同的。 – Tharwen

+0

您能否详细说明一下?我发现,这真的不工作,我期望它如何:( – nihilo90

回答

5

免责声明:多线程是不是我的专长最大面积......

你的问题两者都是真的一样的东西,例如由于EDT正忙于运行while循环,因此您的GUI变得无法响应。这意味着它不能用新的文本值重新绘制按钮,并且它不能对用户输入做出反应。

此外,SwingWorker的每个实例只能运行一次,因此在循环中多次调用​​只运行一次。

我建议创建一个TunerWorker对象,并将该循环放在里面,然后在需要启动循环时创建一个新对象。就像这样:

class TunerListener implements ActionListener { 

private TunerWorker tw = null; 

@Override 
public void actionPerformed(ActionEvent ae) { 

    if (ae.getActionCommand().equals("tune")) { 
     if (tw == null || tw.isDone()) { 
      tune.setText("Stop Tuning"); 
      executing = true; 

      tw = new TunerWorker(); 
      tw.execute(); 

     } else { 
      tune.setText("Start Tuning"); 
      executing = false; 
      tw.cancel(true); 
      } 
     } 
    } 
} 

final class TunerWorker extends SwingWorker<Void, Void> { 

    @Override 
    protected Void doInBackground() { 
     while (!this.isCancelled()) { 
      model.update(); 
     }   
     return null; 
    }  

    @Override 
    protected void done() { 
     if (!this.isCancelled()) { 
      //Removed this code to make the example prettier... 
     } 
    } 
} 

哦,我不知道你试图用firstUpdate做的,所以我把它从例子。希望解决问题的方法不会太难。

编辑:哎呀,该代码实际上并没有工作。现在应该修复。

+0

+1缩小焦点; GUI可以从'process()'安全地更新。 – trashgod

+0

感谢您的支持。真的清除了:) – nihilo90

+0

+1 for'另外,SwingWorker的每个实例只能运行一次,因此在循环中多次调用execute()只会运行一次。这就是我一直在寻找的。 – Tar

6

SwingWorker”仅用于执行一次“。取而代之的是控制工作人员的执行和生命周期,如example所示。