在带有动画的Java应用程序中使用多个计时器

时间:2011-03-14 21:56:32

标签: java animation timer

我正在编写一个Java应用程序,它将在屏幕上滚动乐谱,然后当它穿过中间线时,它将播放音符。

它将根据每分钟的节拍变速。

每节拍一次,我需要一个“勾号”功能,它将获得下一个音符(如果有的话)并开始动画。为了计算这个滴答,我有一个60000ms / bpm / 4的功能。这将与动画计时器分开,因为重绘应该以某种恒定速率调用。

所以我认为我需要Util Timer用于“ticks”和JPanel的swing计时器以及paintComponent()方法中的绘图。

我的问题是:实现这一目标的最佳做法是什么?我已经做了相当多的Java编程,但没有Swing或动画,所以我想学习最好的方法。

由于

内特

1 个答案:

答案 0 :(得分:1)

没有理由使用Timer或TimerTask来解决这个问题。

在这种情况下,您有一系列音符,当您开始演奏时,您可以提前计算每个音符应该播放的确切时间。我假设您已经有某种循环以稳定的速率更新显示。 (例如,每秒30次刷新,或类似的东西)。给定这样一个循环,你需要的只是一个面向事件的类,它可以告诉你是否是时候播放音符。

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

声明上面的数组。然后浏览歌曲中的所有音符,并计算每个音符预期播放的时间。假设您有qurter音符,第一个音符将在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)。