2

1秒間隔でさまざまなアクションを開始することになっているこのタイマーがあります。5 秒のカウントダウン (文字通り) をシミュレートするのは非常に単純なアイデアです。最初に、JLabel が更新され、そのテキストが「5」に設定されます。同時に、小さな mp3 サウンド ファイルが再生され、ユーザーが画面に表示する数字を発声します。それから 1 秒後、テキストは「4」に変更され、別の mp3 が再生されて数字の 4 が再生されます。これがゼロになるまで繰り返されます。

これはすべて機能しますが、視覚的な更新をオーディオ部分と正確に同期させることができません。mp3 は常に、画面が更新される少し前に再生されるようです。最初は、各 mp3 の冒頭に少し余分な無音を入れる必要があるだけだと思っていましたが、うまく同期するまで試行錯誤を繰り返しました。しかし、各 mp3 の前にどれだけ無音を追加しても、画面が更新される前に音声が聞こえます。変化するのは、「1 秒」ごとの更新間のラグだけです。

とにかく、ここに私が取り組んでいるコードがあります。これを同期させるのを手伝ってくれる人はいますか?多分私は2番目のタイマーが必要ですか?それがどのように機能するかわかりません。前もって感謝します!

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

問題の大部分は次のようになります。

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 に答える
1

それらを完全に同期できるとは思えませんが、現在のアプローチがうまくいかない理由は説明できます。

Swing コンポーネントTimer. ラベルのテキストを更新すると、Event Dispatch Threadで再描画がスケジュールされます。スケジュールという言葉に注意し、実行しないでください。

ただし、イベント ディスパッチ スレッドは現在、サウンドの再生でビジーであるため、実際のrepaint操作は を呼び出した後にのみ発生しますmp3.play()

Threadこれで、MP3 を再生するためのスレッド ルールが不明な場合 (許可されている場合)、別のデバイスで(たとえば、Swing 以外のセカンダリ タイマーを使用して) MP3 の再生を試みることができます。ただし、実際の再描画がいつ行われるかを完全に制御することはできず、再描画がスケジュールされているときしか制御できないため、視覚的および聴覚的な更新は依然として同期していない可能性があります。

于 2012-09-01T06:40:25.407 に答える