2

我正在用 Java 制作一个程序,每次用户按下键盘上的按钮时,都会播放一首歌。但是,当我对此进行测试时,按下按键会使歌曲彼此重叠播放,而不是在播放另一首之前停止一首歌曲。这是我在播放器中的代码:

import javax.swing.*;
import javax.sound.sampled.*;
import java.io.*;

public class Player
{

    public void playmusic(String musicfile) {
        File soundFile = new File(musicfile);
        try {
            Clip clip = AudioSystem.getClip();
            if(musicfile.equals("stop")){
                clip.stop();
            }
            else {
                AudioInputStream inputStream= AudioSystem.getAudioInputStream(soundFile);
                clip.open(inputStream);
                //clip.loop(clip.LOOP_CONTINUOUSLY);
                clip.start();
            }
        }
        catch(Exception e)
        {
            System.out.println(e);
        }
    }
}

在我的 Game 类中,我创建了 Player 类的一个实例,称为 play。这是类(与音乐相关的方法是keyPressed()):

 import javax.swing.*;
 import java.awt.*;
 import java.awt.image.BufferedImage; 
 import java.awt.event.*; 

public class Game  extends JPanel implements Runnable, KeyListener{


    private BufferedImage back; 
    private int key; 
    private String[] song;
    private Player play;
    private ImageIcon menu, choose;
    private String screen;



    public Game() {
        new Thread(this).start();   
        this.addKeyListener(this);
        key =-1; 
        play = new Player();
        song = new String[]{"the_greatest_show.wav","a_million_dreams.wav","a_million_dreams_reprise.wav","come_alive.wav","the_other_side.wav","never_enough.wav","this_is_me.wav","rewrite_the_star.wav","tightrope.wav", "never_enough_reprise.wav","from_now_on.wav"};
        letter = 'Z';
        menu = new ImageIcon("menu.png");
        choose = new ImageIcon("select.png");
        screen = "Menu";
    }



    public void run()
    {
        try
        {
            while(true)
            {
                Thread.currentThread().sleep(5);
                repaint();
            }
        }
        catch(Exception e)
        {
        }
    }





    public void paint(Graphics g){

        Graphics2D twoDgraph = (Graphics2D) g; 
        if( back ==null)
            back=(BufferedImage)( (createImage(getWidth(), getHeight()))); 


        Graphics g2d = back.createGraphics();

        g2d.clearRect(0,0,getSize().width, getSize().height);
        switch(screen){
        case("Menu"):
            g2d.drawImage(menu.getImage(), 0, 0, 1000, 700, this);
        break;
        case("Choose"):
            g2d.drawImage(choose.getImage(), 0, 0, 1000, 700, this);
            
        }
        twoDgraph.drawImage(back, null, 0, 0);

    }
    

    public void stopMusic(){
        play.playmusic("stop");
    }





    @Override
    public void keyTyped(KeyEvent e) {
        // TODO Auto-generated method stub

    }





    @Override
    public void keyPressed(KeyEvent e) {
        // TODO Auto-generated method stub

        key= e.getKeyCode();
        char c = (char)(key);
        switch(c){
            case 'A':
                stopMusic();
                play.playmusic(song[0]);
                break;
            case 'S':
                stopMusic();
                play.playmusic(song[1]);
                break;
            
            case 'D':
                stopMusic();
                play.playmusic(song[2]);
                break;
            case 'F':
                stopMusic();
                play.playmusic(song[3]);
                break;
            case 'G':
                stopMusic();
                play.playmusic(song[4]);
                break;
            case 'H':
                stopMusic();
                play.playmusic(song[5]);
                break;
            case 'J':
                stopMusic();
                play.playmusic(song[6]);
                break;
            case 'K':
                stopMusic();
                play.playmusic(song[7]);
                break;
            case 'L': 
                stopMusic();
                play.playmusic(song[8]);
                break;
            case 'V':
                stopMusic();
                play.playmusic(song[9]);
                break;
            case 'B':
                stopMusic();
                play.playmusic(song[10]);
                break;
            default:
                stopMusic();
        }
    }



    @Override
    public void keyReleased(KeyEvent e) {

    }

}

请帮我解决这个问题。先感谢您。

4

2 回答 2

2

如果您getClip()在方法内部调用,您将停止第二个剪辑,因为您丢失了对前一个剪辑的引用(并将继续在后台播放)。 AudioSystem.getClip()返回一个剪辑,而不是当前剪辑。

当您播放下一首歌曲时,您正在同时播放两个剪辑:第一个剪辑和当前剪辑,因为您停止的剪辑是一个全新的剪辑。

Clip[0]      Clip[1]         Clip[2]
Song 1   (nosong-stopped)    Song 2

为了解决这个问题,你可以做clip一个全局变量,所以当stop()close()被调用时,当前歌曲clip就是选择的歌曲(你只有一个剪辑)。

Clip clip = null;
//...

public void playmusic(String musicfile) {
    File soundFile = new File(musicfile);
    try 
    {
       if(musicfile.equals("stop")) 
       {
           if (clip!=null) //do not nest it to the previous condition ...
           {
             clip.stop();
             clip.flush();
             clip.close();
           }
       }
       else   //...so no song is played if you called stop and clip was null
       {
           AudioInputStream inputStream= AudioSystem.getAudioInputStream(soundFile);
           if (clip == null || !clip.isOpen())
               clip = AudioSystem.getClip();
           clip.open(inputStream);
           //clip.loop(clip.LOOP_CONTINUOUSLY);
           clip.start();
        }
    }
    catch(Exception e)
    {
        System.out.println(e);
    }
}
于 2021-02-17T04:59:04.497 回答
0

替换 playmusic() 方法并检查

public void playmusic(String musicfile) {
        
        try {
            Clip clip = AudioSystem.getClip();
            if(musicfile.equals("stop")){
                clip.stop();
            }
            else {
                File soundFile = new File(musicfile);
                AudioInputStream inputStream= AudioSystem.getAudioInputStream(soundFile);
                clip.open(inputStream);
                //clip.loop(clip.LOOP_CONTINUOUSLY);
                clip.start();
            }
        }
        catch(Exception e)
        {
            System.out.println(e);
        }
    }
于 2021-02-17T04:56:00.897 回答