我想要一种非常简单的方法来从 Java 应用程序播放 mp3 文件。经过一番研究,我发现最新版本的 Java 7 SE 是用 JavaFX 打包的,所以我想我会尝试一下。这个问题不是关于播放 mp3 文件,而是关于让 JavaFX 以一种行为良好的方式工作。
因此,在我对 JavaFX 的第一次实验中,我使用了一些在 stackoverflow 帖子中建议的代码(请参见此处),并创建了以下测试程序:
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
public class progtest extends Application
{
/*---------------------------------------------------------*\
FUNCTION: main()
\*---------------------------------------------------------*/
public static void main(String args[])
{
launch(args);
} /* END: main() */
/*---------------------------------------------------------*\
FUNCTION: start()
\*---------------------------------------------------------*/
@Override
public void start(Stage stage)
{
Media medMsg
=
new Media(getClass().getResource("msg.mp3").toExternalForm());
MediaPlayer medplMsg = new MediaPlayer(medMsg);
medplMsg.play();
System.out.println("Here.\n");
} /* END: start() */
}
(这比我原来的测试程序稍微复杂一点:这个版本是在jewelsea 提出的建议之后出现的,该建议是为了回应我之前发布的关于让程序运行的问题(见这里)。)
为了编译我使用的这段代码:
javac -cp "c:\Program Files\Oracle\JavaFX 2.1 Runtime\lib\jfxrt.jar";..\bin -d ..\bin ..\src\progtest.java
而且,为了运行代码,我进入了我的 ..\bin 目录并使用了:
java -cp .;"c:\Program Files\Oracle\JavaFX 2.1 Runtime\lib\jfxrt.jar" progtest
该程序运行并播放剪辑播放。但是,除非我按 Ctrl-C,否则程序不会返回到命令提示符。
这种行为似乎是某种线程问题。我已经多次看到这种行为与 Java 线程一起使用(遗憾的是,在允许程序优雅退出时存在真正的问题)。
所以,我想,也许如果我将代码放在它自己的线程中,然后在该线程结束时结束程序的主线程,一切都会好起来的。(我可以看出这并不完全是一个有说服力的想法,但无论如何,我想我会尝试。)所以,我编写了以下第二个版本的代码:
这是主线程:
import javafx.application.Application;
import javafx.stage.Stage;
import Msg.*;
public class progtest2 extends Application
{
/*---------------------------------------------------------*\
FUNCTION: main()
\*---------------------------------------------------------*/
public static void main(String args[])
{
launch(args);
} /* END: main() */
/*---------------------------------------------------------*\
FUNCTION: start()
\*---------------------------------------------------------*/
@Override
public void start(Stage stage)
{
Msg msgTime = new Msg();
msgTime.passClass(getClass());
msgTime.start();
try
{
msgTime.join();
}
catch (InterruptedException e)
{
}
System.out.println("Here.\n");
} /* END: start() */
}
下面是实际播放 mp3 文件的 Msg 线程的代码:
package Msg;
import KeyIO.*;
import javafx.application.Application;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
public class Msg extends Thread
{
private Class classRt = null;
/*--------------------------------------------------------*\
FUNCTION: passClass()
\*--------------------------------------------------------*/
public void passClass(Class rt)
{
classRt = rt;
} /* END: passClass() */
/*--------------------------------------------------------*\
FUNCTION: run()
\*--------------------------------------------------------*/
public void run()
{
Media medMsg
= new Media(classRt.getResource("msg.mp3").toExternalForm());
MediaPlayer medplMsg = new MediaPlayer(medMsg);
medplMsg.play();
System.out.println("Leaving Msg thread.\n");
} /* END: run() */
}
(我使用与上述相同的命令(比照文件名和类名)构建并运行这些文件。)
该程序运行并播放 mp3 文件。在您听到文件之前,您会看到“Leaving Msg thread”。然后是“Here.”,如您所见,它分别来自 Msg 线程和主线程。但是,同样,程序并没有结束。我必须按 Ctrl-C 才能返回命令提示符。
我在主线程的末尾放了一个 System.exit() 调用,只是为了看看行为会是什么。行为是没有听到剪辑。似乎 System.exit() 调用在播放剪辑之前结束了该过程。
因此,接下来我尝试将以下几行放在 System.out.println("Here.\n"); 之间 和我所做的 System.exit() 调用:
System.out.print("Press ENTER to end...");
KeyIO.ReadLine();
(KeyIO 是我做的一个类,只是为了简单地做键盘输入输出。细节在这里并不相关。)
我认为这只会阻止主线程继续前进,直到播放剪辑。
但不是。相反,该剪辑没有播放。当我按 ENTER 时,程序退出而不播放剪辑。
好的,所以现在我留下了键盘输入阻塞代码,但我取出了 System.exit() 调用。现在播放了音频剪辑,但程序没有再次结束。
啊!
有什么想法可以优雅地让它以一种显而易见的方式工作吗?我只想打电话播放剪辑,然后我希望能够结束程序。
先感谢您!