2011-03-14 57 views
2

我正在編寫一個Java應用程序,它將在屏幕上滾動樂譜,然後當它穿過中間線時,它將播放音符。在帶有動畫的Java應用程序中使用多個定時器

它將根據每分鐘節拍變化速度。

每拍一拍我需要一個「勾號」功能,它將獲得下一個音符(如果有的話)並開始其動畫。要計算此刻度,我有一個函數60000ms/bpm/4。這將與動畫計時器分開,因爲重繪應該以某種恆定速率進行調用。

所以我想我需要利用計時器的「滴答」和JPanel搖擺計時器和繪製paintComponent()方法。

我的問題是:完成此操作的最佳實踐是什麼?我已經做了大量的Java編程,但沒有Swing或動畫,所以我想學習最好的方法來做到這一點。

感謝

內特

+0

這是我到目前爲止...... – Nate 2011-03-17 16:34:52

+0

我有一個驅動類與util.Timer和TimerTask每毫秒。在「tick」點處,它調用tick()方法,在tick中查找歌曲中的音符,如果有,則將其添加到NoteEvents的Scroller(擴展JPanel)集合,Scroller使用其paintComponent方法更新它。 – Nate 2011-03-17 16:41:56

回答

1

沒有理由使用定時器或TimerTask的來解決這個問題。

在這種情況下,您有一系列筆記,當您開始玩時,您可以提前計算每個筆記應播放的確切時間。我假設你已經有一些循環以穩定的速度更新顯示。 (例如每秒刷新30次,或類似的)。考慮到這樣一個循環,所有你需要的是一個面向事件的類,它可以告訴你是否該彈奏音符了。

long noteTime[] = new long[numberOfNotes]; 
long startTime = System.currentTimeMillis(); 

聲明上面的數組。然後瀏覽歌曲中的所有音符,並計算每個音符預期播放的時間。假設你有幾分音符,第一個音符將在startTime播放,第二個音符在startTime之後跳動,第三個在開始時間之後跳動兩次,等等。這是計算節拍時間並使用它的地方。只需計算每個音符的實際時間值即可播放。

然後,在你的事件循環的中間被刷新顯示,包括下面的代碼:

int nextNote = 0; 
while (event_loop_condition) { 
    . 
    . 
    . 
    if (System.currentTimeMillis()>noteTime[nextNote]) { 
     playNote(nextNote++); 
    } 
    . 
    . 
    . 
} 

的一點是,你已經有一個事件循環,所有你需要知道的是它是否現在還沒有播放音符,這將爲你做到這一點。另一方面,如果你沒有處理刷新,並且你確實想要在一個線程上執行此操作,則可以在一個線程上調用follow方法,並且它會在正確的時間播放所有的音符:

playAllNotes() { 
    for (int i=0; i<numberOfNotes; i++) { 
     Thread.sleep(noteTime[i]-System.currentTimeMillis()); 
     playNote(i); 
    } 
} 

睡眠聲明將延遲,直到應該播放音符的時間,並在那個時候播放。然後它會睡覺,直到下一個音符播放的時間。

要注意兩種方法的重要之處在於播放音符的延遲不會在下一個音符上覆合。說一些系統實用程序,並將延遲一個音符延遲50ms。下一個音符不會被這個延遲,因爲你計算了所有音符的所有時間都要在前面播放。考慮到線程競爭CPU時間,你將會遇到線程/進程競爭,並且在音符播放的時候會有很小的變化,但它們永遠不會複合!

如果您想了解更多信息,很多程序員會在我的網站上錯誤地使用計時器(請參閱discussion of Timers)。

+0

謝謝,這是我最終發現的答案,但我忘了把它放在這裏。 – Nate 2013-01-15 17:23:17

相關問題