2

我有这个计时器,它应该以 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);
        }
    }
}
4

2 回答 2

1

我非常怀疑您是否能够完美地同步这些内容,但我可以解释为什么当前的方法行不通。

Swing 组件必须在Event Dispatch Thread上更新,就像使用Timer. 当您更新标签的文本时,它将在Event Dispatch Thread上安排重绘。注意schedule这个词,而不是perform

但是,Event Dispatch Thread目前正忙于播放您的声音,所以实际repaint操作只有在您调用mp3.play().

现在您可以(如果允许,不确定播放 MP3 的线程规则)尝试在不同的设备上播放 mp3 Thread(例如,通过使用辅助非 Swing 计时器)。但是,由于您永远无法完全控制实际重绘何时发生,并且只能控制重绘计划的时间,因此视觉和听觉更新仍然可能不同步。

于 2012-09-01T06:40:25.407 回答
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 是(可察觉的)滞后或延迟的真正原因。

于 2012-09-02T06:30:20.143 回答