[英]Unexpected behaviour with Thread.sleep()
我構建了一個簡單的程序來播放一首歌。
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
打印到控制台。 我該如何解決這個問題?
您正在阻止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應用程序。)
在MediaPlayer
上操作是異步的。 這解釋了為什么在實際音樂開始之前打印"Fade"
。 從文檔 :
MediaPlayer的操作本質上是異步的。 玩家不准備立即響應命令,直到其狀態轉換為
MediaPlayer.Status.READY
,這實際上通常在媒體預滾動完成時發生。 但是,在狀態為READY
之前對玩家提出的某些請求將在輸入該狀態時生效。 這些包括在READY
轉換之前調用play()
而不調用pause()
或stop()
,以及設置autoPlay
,balance
,mute
,rate
,startTime
,stopTime
和volume
屬性中的任何一個。
您可以通過輪詢其狀態來控制玩家是否實際正在玩游戲。 從play()
(強調我的):
開始播放媒體。 如果之前暫停,則播放將在暫停時恢復。 如果停止播放,則從startTime開始播放。 實際播放時,狀態將設置為
MediaPlayer.Status.PLAYING
。
要在播放器開始播放時注冊回調,您可以通過添加更改偵聽器或通過調用setOnPlaying(runnable)
直接設置事件處理程序來掛接到onPlayingProperty
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.