【问题标题】:java audio playing wont stopjava音频播放不会停止
【发布时间】:2017-03-06 08:08:43
【问题描述】:

好的,我有这个问题:我的音频开始正常播放,但即使在“clip.stop()”或“clip.close()”之后它也不会停止......你知道该怎么做才能停止它? (我什至可以接受静音,我真的很绝望)

public class Main {
     //audio playing
    public static void audio(boolean a) {
        try {

            File file = new File("textures/Main_theme.wav");
            Clip clip = AudioSystem.getClip();
            clip.open(AudioSystem.getAudioInputStream(file));

            if(a == true){
            // this loads correctly, but wont stop music
            clip.stop();
           System.out.println(a);
            }
            else{
            clip.start();

            }
        } catch (Exception e) {
            System.err.println("Put the music.wav file in the sound folder if you want to play background music, only optional!");
        }
    }


    private static String arg;

    public static void main(String[] args){

   //picture loading ... ignorable now

    arg = "textures/ccc.gif";
    JFrame f = new JFrame();
    JPanel p = new JPanel();
    JLabel l = new JLabel();
    ImageIcon icon = new ImageIcon(arg);    
    f.setSize(480, 360);
    f.setVisible(true);
    l.setIcon(icon);
    p.add(l);
    f.getContentPane().add(p);
    f.setLocationRelativeTo(null);
    f.setResizable(false);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

     //calling audio method to play sound (works)
    audio(false);

    //should stop music and run another class
    KeyListener action = new KeyListener()
    {
        @Override
        public void keyPressed(KeyEvent e) {
        //trying to stop music
            f.dispose();
            try {

                Menu.menu(args);
                Main.audio(true);

            } catch (IOException e1) {
            //rest of code ... ignorable    
                e1.printStackTrace();
            }

        }

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

        }

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

        }

    };
    f.addKeyListener( action );

        }
    }

【问题讨论】:

  • 当您尝试调用 stop 时,您正在对未播放的 Clip 调用 stop,您需要使用与您调用 @987654326 的 Clip 相同的引用@开

标签: java swing audio javasound audio-player


【解决方案1】:

你需要退后一步,想想你在做什么。

您正在创建 Clip 并且正在播放它。在未来的某个时候,您创建一个新的Clip 并尝试停止。这两个Clips 有什么共同点?它们是如何连接的?答案是,他们不是。加载同一个文件以分隔Clips 并单独播放它们是很合理的。

相反,您需要停止之前启动的 Clip 实例。

因为我很懒,我会先将音频功能封装到一个简单的类中。

public class Audio {

    private Clip clip;

    protected Audio() {
    }

    public Audio(File source) throws LineUnavailableException, MalformedURLException, IOException, UnsupportedAudioFileException {
        this(source.toURI().toURL());
    }

    public Audio(URL source) throws LineUnavailableException, IOException, UnsupportedAudioFileException {
        this(source.openStream());
    }

    public Audio(InputStream source) throws LineUnavailableException, IOException, UnsupportedAudioFileException {
        init(source);
    }

    protected void init(File source) throws LineUnavailableException, MalformedURLException, IOException, UnsupportedAudioFileException {
        init(source.toURI().toURL());
    }

    protected void init(URL source) throws IOException, LineUnavailableException, UnsupportedAudioFileException {
        init(source.openStream());
    }

    protected void init(InputStream source) throws LineUnavailableException, IOException, UnsupportedAudioFileException {
        clip = AudioSystem.getClip();
        clip.open(AudioSystem.getAudioInputStream(source));
    }

    public void setRepeats(boolean repeats) {
        clip.loop(repeats ? Clip.LOOP_CONTINUOUSLY : 1);
    }

    public void reset() {
        clip.stop();
        clip.setFramePosition(0);
    }

    public void play() {
        clip.start();
    }

    public void stop() {
        clip.stop();
    }

    public boolean isPlaying() {
        return clip.isActive();
    }
}

“为什么?”你问,因为现在我可以创建代表特定声音的子类并加载它们,而无需关心或记住音频的来源是什么,例如......

public class MainTheme extends Audio {

    public MainTheme() throws LineUnavailableException, MalformedURLException, IOException, UnsupportedAudioFileException {
        init(getClass().getResource("textures/Main_theme.wav"));
    }

}

现在,我可以在需要时轻松创建“主题”音频,而不必关心它的来源

这也意味着我可以将MainTheme 传递给程序的其他需要Audio 实例的部分并简单地卸载管理

然后你只需要创建一个类的实例并根据需要启动/停止它,例如...

package test;

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            JButton btn = new JButton("Click");
            btn.addActionListener(new ActionListener() {

                private Audio audio;

                @Override
                public void actionPerformed(ActionEvent e) {
                    try {
                        if (audio == null) {
                            audio = new MainTheme();
                        }

                        if (audio.isPlaying()) {
                            audio.stop();
                        } else {
                            audio.play();
                        }
                    } catch (LineUnavailableException | IOException | UnsupportedAudioFileException ex) {
                        ex.printStackTrace();
                    }
                }
            });

            add(btn);
        }
    }
}

【讨论】:

  • 谢谢,它帮了我很多,我只是对你的子类说有些麻烦:“公共类型 MainTheme 必须在自己的文件中定义,不能在显式调用构造函数时引用实例方法” ...你知道如何解决这个问题吗?
  • 您是否复制了包含的 MainTheme 类
  • 是的,把它放在最后一个音频类“}”的正下方(顺便说一句,我真的是个傻程序员,很抱歉:'))
  • Java 更喜欢将其类放在自己的文件中(您可以使用内部类,但要开始使用,请尝试每个类使用单个文件)
  • 好的,很酷....这解决了类问题,但仍然说:“在显式调用构造函数时无法引用实例方法”:super(getClass().getResource("纹理/Main_theme.wav"));
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-13
  • 1970-01-01
相关资源
最近更新 更多