我构建了一个播放歌曲的简单程序。
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import java.io.File;
import javax.swing.*;
import java.awt.*;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.application.Platform;
import javafx.scene.Group;
public class Fade {
private void initAndShowGUI() {
// This method is invoked on Swing thread
JFrame frame = new JFrame("FX");
final JFXPanel fxPanel = new JFXPanel();
frame.add(fxPanel);
frame.setVisible(true);
Platform.runLater(new Runnable() {
@Override
public void run() {
initFX(fxPanel);
}
});
}
private void initFX(JFXPanel fxPanel) {
// This method is invoked on JavaFX thread
Group root = new Group();
Scene scene = new Scene(root, 500, 500, true);
fxPanel.setScene(scene);
try {
String bip = new File("./Sound/Welcome To The Show - L1-5.mp3").toURI().toString();
Media hit = new Media(bip);
MediaPlayer mediaPlayer = new MediaPlayer(hit);
mediaPlayer.play();
Thread.sleep(10000);
System.out.println("Fade");
} catch (Exception e) {
System.out.println("Exception");
System.out.println(e);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Fade().initAndShowGUI();
}
});
}
}
然而,当运行此代码时,Thread.sleep(10000)
在歌曲开始播放之前运行而不是开始播放的歌曲,然后10秒后fade
将打印到控制台。我该如何解决这个问题?
答案 0 :(得分:4)
您正在阻止JavaFX应用程序线程,因此它无法正常工作(可能包括处理媒体播放器的启动指令),直到您的方法完成。您永远不应该阻止此线程,因为它可以保证UI不响应。
在JavaFX中实现暂停的最简单方法是使用PauseTransition
:
MediaPlayer mediaPlayer = new MediaPlayer(hit);
mediaPlayer.play();
// never do this:
//Thread.sleep(10000);
PauseTransition pause = new PauseTransition(Duration.millis(10000));
pause.setOnFinished(e -> {
System.out.println("Fade");
});
pause.play();
(顺便说一句,我认为你的真实应用程序有一些理由混合swing和JavaFX。否则你应该把它变成一个纯JavaFX应用程序。)
答案 1 :(得分:3)
在MediaPlayer
上操作是异步的。这解释了为什么在实际音乐开始之前打印"Fade"
。来自the documentation:
MediaPlayer的操作本质上是异步的。玩家不准备立即响应命令,直到其状态转换为
MediaPlayer.Status.READY
,这实际上通常发生在媒体预滚动完成时。然而,在状态为READY
之前由玩家提出的某些请求将在输入该状态时生效。其中包括在play()
转换之前调用pause()
而无需调用stop()
或READY
,以及设置任何autoPlay
,balance
},mute
,rate
,startTime
,stopTime
和volume
属性。
您可以通过轮询其status来控制玩家是否真正在玩游戏。来自play()
(强调我的):
开始播放媒体。如果之前暂停,则播放将在暂停时恢复。如果停止播放,则从startTime开始播放。 实际播放时,状态将设置为
MediaPlayer.Status.PLAYING
。
要在播放器开始播放时注册回调,您可以通过添加更改侦听器或通过调用onPlayingProperty
直接设置事件处理程序来挂钩setOnPlaying(runnable)