2013-06-23 43 views
0

我想在自定義MIDI播放器上實現重複功能,但我無法實現重複功能。以下是我正在使用的課程:向簡單的MIDI播放器添加重複功能

NotePlayer - 使用Java的MIDI包播放MIDI音符。

GuitarTunerGUI

  • 接口到NotePlayer類。
  • 爲每個吉他字符串提供六個JButtons,用於選擇所需調諧的JComboBox以及用於切換重複功能的JCheckBox。
  • 提供toggleRepeat()用於切換repeatEnabled字段,該字段是GuitarTunerGUI類的私有字段。

我創建了一個SwingWorker,負責在單獨的線程中播放MIDI音符。這解決了在筆記播放時保持GUI響應的問題。 但是,啓用重複並且用戶按下多個按鈕時會出現問題。

當用戶按下六個Jbutton將之一聽者執行以下操作:

public void actionPerformed(ActionEvent event) { 
    // The note param is a private field of the listener object 
    MusicianWorker clapton = new MusicianWorker(note); 
    clapton.execute(); 
} 

的執行方法執行以下操作:

protected Void doInBackground() throws Exception { 
    do { 
     NotePlayer.playNote(thisNote); 
     try { 
      Thread.sleep(3000); 
     } catch (InterruptedException ex) { 
      System.out.println(ex.getMessage()); 
     } 
    } while (repeatEnabled); 

    return null; 
} 

當用戶按壓多個按鈕沒有問題出現切換重複。例如,當順序按下'A'按鈕和'E'按鈕時,創建兩個線程,並且'A'和'E'音符是兩個都重複播放,直到repeatEnabled被切換爲止。當用戶按下一個JButton時,我需要首先確定是否有任何工作線程正在執行,如果這樣,在播放指定音符之前殺掉這些線程。預先感謝您的時間和反饋。

+0

類似的問題被檢查[這裏](http://stackoverflow.com/q/17226579/230513Z)。 – trashgod

回答

0

您需要保持工人之間的共享狀態。引入新的布爾變量「玩」。在執行前檢查播放標誌是否設置爲true,執行後再次設置爲false。

0

你給出的代碼很棒,只需要稍微調整就可以了。當你創建你的SwingWorker時,你應該在一個實例變量中跟蹤它(如果你打算在某個時候想要播放多個音符,那麼可以在List中)。然後,在播放新音符前,檢查最後一個音符是否完成,如果沒有,則取消它。

取消是否對您的MusicianWorker有影響取決於您。工作線程將被中斷,這意味着如果您的Thread.sleep方法在運行時會過早終止 - 您必須檢查文檔以查看它對NotePlayer的影響。

最後,似乎根本不需要使用SwingWorker,因爲您的後臺任務不與UI進行交互。您可能需要調查Executors

你可以嘗試這樣的事:

public class AlbertHall { 
    private final ExecutorService es = Executors.newSingleThreadExecutor(); 
    // No longer a local variable in the listener 
    private Future<Void> clapton; // ... or maybe a Collection of Futures 

    private class Listener implements ActionListener { 
    private final Note note; 

    public Listener(Note note) { 
     this.note = note; 
    } 

    public void actionPerformed(ActionEvent event) { 
     // Watch out, Clapton may finish after you have asked if he is done 
     // but before you call cancel 
     if (clapton != null && !clapton.isDone()) clapton.cancel(true); 

     // You may need to have a wait loop here if Clapton takes a while 
     // to leave the stage 

     // Next note 
     clapton = es.submit(new MusicianWorker(note)); 
    } 
    } 

    static class MusicianWorker implements Runnable { 
    private final Note note; 

    public MusicianWorker(Note note) { 
     this.note = note; 
    } 

    public void run() { 
     boolean cancelRequested = false; 
     do { 
     NotePlayer.playNote(thisNote); 
     try { 
      Thread.sleep(3000); 
     } catch (InterruptedException ex) { 
      // Looks like we got cancelled 
      cancelRequested = true; 
     } 
     } while (repeatEnabled && !cancelRequested); 
    } 
    } 
} 
+0

非常感謝您的反饋,並很抱歉沒有及時回覆。我有一段時間沒有機會看看我的吉他調音器代碼。我會嘗試你的建議,並讓你知道結果如何。 – Denton