2012-05-05 90 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所示。