我有一个用 Swing 编写的应用程序,我想在其中使用 JavaFX 的 MediaPlayer 来播放音频/声音文件。
这是主文件的精简版:
class MyApp
{
private MyApp myApp;
private JFrame myFrame;
private Media media;
private MediaPlayer mediaPlayer;
public static void main(String[] args)
{
Runnable thread = new Runnable()
{
public void run()
{
myApp = new MyApp();
}
};
SwingUtilities.invokeLater(thread);
}
public void MyApp()
{
//this is called by SwingUtilities.invokeLater();
URL url = //getting URL to a sound file stored locally//;
media = new Media(url.toString() );
mediaPlayer = new MediaPlayer( media );
mediaPlayer.play();
myFrame = new JFrame(); //building swing UI here
}
这似乎在 Netbeans 中有效。但是,当 Netbeans 构建 .jar 并且我尝试运行 .jar 时,我在 .jar 目录中得到一个错误日志文件,其中包含一些内存/线程错误。
我是否需要使用 Platform.runLater()
方法来让它工作?还是我做错了什么?
最佳答案
当与 Swing 应用程序中嵌入的 JavaFX 控件交互时,一定要在 Platform.runLater
调用中执行此操作,而不是 Swing.invokeLater
调用。
您还应该确保 JavaFX 系统已初始化,并且(最好)应用程序已使用 JavaFX 打包工具进行了处理,如本文所述:Playing audio using JavaFX MediaPlayer in a normal Java application? .
虽然在 JavaFX 线程之外运行一些创建一些 JavaFX 控件的代码适用于大多数控件,甚至与某些控件的某些交互有时似乎在 JavaFX 线程之外工作,但在实践中我发现它不值得冒险和潜在的模糊错误或这样做时可能会遇到竞争条件。 JavaFX 设计时考虑了 UI 的单线程交互模型,因此最好使用 Platform.runLater
等工具保持这种方式。带有事件分派(dispatch)线程的 Swing 也是如此。您需要将这两个框架之间的线程交互分开。
查看问题中 MyApp 代码中的 5 行,我有以下建议。
在哪个线程上执行并不重要,因为它不与任何框架交互:
URL url = //getting URL to a sound file stored locally//;
使用 JavaFX 控件应该包装在 Platform.runLater 中:
media = new Media(url.toString() );
mediaPlayer = new MediaPlayer( media );
mediaPlayer.play();
与 Swing 框架交互,因此应该包装在 Swing.invokeLater
中:
myFrame = new JFrame(); //building swing UI here
注意:只调用一个runLater是不够的,你还需要在MediaPlayer播放调用之后从runLater主体内部调用Swing jframe。
关于java - 在现有的 Swing 项目中使用 JavaFX 的 MediaPlayer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12549793/