我有这个Timer,应该以1秒的间隔启动各种动作。这是一个非常简单的想法,模拟5秒倒计时(字面意思)。在开始时,更新JLabel以将其文本设置为“5”。同时,播放一个小的mp3声音文件,发出用户在屏幕上看到的数字。然后,一秒钟之后,文本将更改为“4”,并播放一个不同的mp3播放数字4。依此类推,直到我们达到零。
这一切都有效,但我无法通过视觉更新与音频部分精确同步。在屏幕更新之前,mp3似乎总是稍微播放。起初,我认为我只需要在每个mp3的开头添加一点额外的沉默,然后尝试同步,直到事情同步为止。但无论我在每个mp3前面有多少沉默,我仍然会在屏幕更新之前听到音频。所有这些变化都是每次“一秒钟”更新之间的延迟。
无论如何,这是我正在使用的代码。谁能帮助我让它同步?也许我需要第二个计时器?我不确定这是怎么回事。提前谢谢!
class Countdown extends JFrame implements ActionListener {
private Timer countdownTimer = new Timer(1000, this);
int countdownSeconds;
MyJFrame myFrame;
public Countdown(MyJFrame thisFrame) {
int countdownSeconds = 5;
countdownTimer.start();
myFrame = thisFrame;
}
@Override
public void actionPerformed(ActionEvent e) {
if (countdownSeconds == 0) {
myFrame.updateCountdown(myFrame, "Go");
SoundEffect.play("launch.mp3");
countdownTimer.stop();
} else {
myFrame.updateCountdown(myFrame, Integer.toString(countdownSeconds));
if (countdownSeconds == 5) {SoundEffect.play("five.mp3");}
if (countdownSeconds == 4) {SoundEffect.play("four.mp3");}
if (countdownSeconds == 3) {SoundEffect.play("three.mp3");}
if (countdownSeconds == 2) {SoundEffect.play("two.mp3");}
if (countdownSeconds == 1) {SoundEffect.play("one.mp3");}
countdownSeconds--;
}
}
}
public void updateCountdown(MyJFrame thisFrame, String numSec) {
lblCountdown.setText(numSec);
}
import java.io.FileInputStream;
import javazoom.jl.player.Player;
public class SoundEffect {
public static void play(String mp3File) {
try {
FileInputStream mp3_file = new FileInputStream(mp3File);
Player mp3 = new Player(mp3_file);
mp3.play();
}
catch(Exception e) {
System.out.println(e);
}
}
}
答案 0 :(得分:1)
我非常怀疑你能否完美地同步这些,但我可以解释为什么当前的方法不起作用。
必须在事件调度线程上更新Swing组件,就像使用Timer
一样。更新标签文本时,它将在事件调度线程上安排重新绘制。请注意计划这个词,而不是执行。
但是,事件调度线程当前正忙于播放您的声音,因此实际的repaint
操作只会在您调用mp3.play()
后发生。
现在你可以(如果允许,不确定播放MP3的线程规则)尝试在另一个Thread
上播放mp3(例如,通过使用辅助非Swing计时器)。但是,由于您永远无法完全控制实际重绘的时间,并且只能控制重新安排的时间,因此视觉和听觉更新仍然可能不同步。
答案 1 :(得分:1)
问题的主要部分归结为:
if (countdownSeconds == 5) {SoundEffect.play("five.mp3");}
..导致..
public class SoundEffect {
public static void play(String mp3File) {
try {
FileInputStream mp3_file = new FileInputStream(mp3File);
Player mp3 = new Player(mp3_file);
mp3.play();
}
catch(Exception e) {
System.out.println(e);
}
}
}
哇!现在不是 加载 剪辑的时候了!
相反,它们应该在计时器启动之前加载。我认为文件I / O是(可感知的)延迟或延迟的真实原因。