Java swing声音播放提前结束

时间:2015-01-06 19:29:03

标签: java swing audio javasound

在Java swing应用程序中,以下片段应该发出警报。它开始运行但过早停止,而不是总是在同一时间停止(即有时它几乎立即停止,有时在较长的延迟后停止,但通常它没有完成播放整个声音文件)。可能导致这种情况的原因是什么?

我已尽力创建一个仍存在问题的最小示例:

package monster;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.io.File;
import javafx.embed.swing.JFXPanel;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Example_2 extends JPanel {

    protected static final long serialVersionUID = 1L;

    public Example_2() {
        setPreferredSize(new Dimension(100,100));
        setBackground(Color.white);
        createPanel();
    }

    public static void main(String[] args) {
        Example_2 e = new Example_2();
        JFrame f    = new JFrame();
        f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        f.add(e, BorderLayout.CENTER);
        f.pack();
        f.setVisible(true);
        f.repaint();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        new Thread(
            new Runnable() {
                public void run() {
                    try {
                        File f = new File("sound/siren_short.wav");
                        String url = "file:///"+f.getAbsolutePath().replaceAll("\\\\","/").replaceAll(" ", "%20");
                        MediaPlayer mp = new MediaPlayer(new Media(url));
                        mp.play();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
    }

    public static JFXPanel createPanel() {
        return new JFXPanel();
    }

}

1 个答案:

答案 0 :(得分:1)

在当前示例代码“Example2”中发布,它看起来像main()执行和退出。是的,对MediaPlayer的调用启动了后台线程,但我猜测当main()结束时,这也终止了MediaPlayer线程(也许是因为它只有守护进程状态)。我自己还没有使用过MediaPlayer,所以我不知道这种行为是否会导致。

这是一个简单的测试:添加以下行。

Thread.sleep(5000); // pauses 5 seconds
在repaint()调用之后,

或类似于main()的结尾。数字是毫秒:使用比声音长度更长的数字。声音现在完成了吗?您可能必须将新的代码行放在 try ... catch 块中。

如果有机会,请查看Thread()的api。当你到达页面时,我建议你搜索“守护进程”。有一些测试或设置守护程序状态的方法,以及对状态意味着什么的简洁解释。有可能如果你将runnable设置为 not 是一个守护进程,程序(如图所示)将播放一次然后挂起而无法终止它,除非通过Eclipse杀死它(如果它是在Eclipse中运行)或通过OS任务管理器运行。

我没有深入研究Eclipse中的调试线程 - 恐怕我不能在那里提供任何建议。

Andrew Thompson提出了一个很好的建议,即使用 Clip 。这有利于我们保持“熟悉”的领域。我经常使用 Clip ,但不使用JavaFX库。如果您已经使用了 Clip ,那么肯定需要我建议的代码行(Thread.sleep)以允许声音播放完成。

这是一个理论:加载和执行play()命令的代码是非守护进程。但是,将声音数据传递到线路的后台进程是守护进程。如果是这种情况,那么我描述的行为(主线程完成后终止)将是一致的。