在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();
}
}
答案 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()命令的代码是非守护进程。但是,将声音数据传递到线路的后台进程是守护进程。如果是这种情况,那么我描述的行为(主线程完成后终止)将是一致的。