这里的问题在于TimeUnit.SECONDS.sleep(5); 调用。此方法将当前线程设置为睡眠状态。在您的情况下,该线程是 JavaFX 应用程序线程。这会导致整个应用程序“冻结”(如果添加一些 GUI 元素会更明显),因此会执行 mediaPlayer.play(); 命令,但由于睡眠功能而立即“冻结”。在`TimeUnit.SECONDS.sleep(5); 调用之后,您为MediaPlayer 设置新的开始和结束时间并再次执行play(),以便轨道在新的开始时间开始。这就是为什么只播放最后一个片段的原因。
现在解决方案:
您永远不应在 JavaFX 应用程序线程上调用 Thread.sleep() 或类似方法。但是在您的情况下,您必须在播放片段之间等待一定的时间。第一种方法是在新线程上调用Thread.sleep() 或TimeUnit.SECONDS.sleep(5);,并在JFX 应用线程上调用Mediaplayer 方法。但这不能正常工作,因为您没有设置调用线程的“顺序”。有多种方法可以做到这一点(通过Semaphores、Locks and Conditions、JavaFX Concurrency 等等......)
我试图通过一些快速而肮脏的编程来解决您的问题,但我遇到了mediaPlayer.setStopTime(Duration.millis()); 的问题。它似乎不适用于我的计算机,因此文件总是播放到最后。我添加了一个停止按钮来模拟自动停止。
下面的类设置新的开始和端点并播放片段。如果媒体播放器停止,它会调用 LittleMediaScheduler 类的下一个片段。
public class LittleMediaHelper implements Runnable {
public double startTime;
public double endTime;
public MediaPlayer player;
public int id;
public LittleMediaScheduler scheduler;
public LittleMediaHelper(double startTime, double endTime,
MediaPlayer player, int id) {
this.startTime = startTime;
this.endTime = endTime;
this.player = player;
this.id = id;
}
public LittleMediaScheduler getScheduler() {
return scheduler;
}
public void setScheduler(LittleMediaScheduler scheduler) {
this.scheduler = scheduler;
}
@Override
public void run() {
Platform.runLater(new Runnable() {
@Override
public void run() {
player.setStartTime(Duration.millis(startTime));
player.setStopTime(Duration.millis(endTime));
System.out.println(player.getStartTime());
System.out.println(player.getStopTime());
player.play();
player.setOnStopped(new Runnable() {
@Override
public void run() {
int idtmp = id + 1;
System.out.println("NEXT " + idtmp);
scheduler.call(idtmp);
}
});
}
});
}
}
这个类负责在新线程上休眠一定量,并在成功休眠后调用下一个 LittleMediaHelper 类播放功能。
public class LittleMediaScheduler {
private ArrayList<LittleMediaHelper> hArrL;
private int SLEEPTIME = 2000;
public LittleMediaScheduler(LittleMediaHelper... helpers) {
this.hArrL = new ArrayList<>();
for (LittleMediaHelper h : helpers) {
h.setScheduler(this);
System.out.println(h.startTime);
this.hArrL.add(h);
}
System.out.println(hArrL.size());
}
public void init() {
Thread t = new Thread(this.hArrL.get(0));
t.start();
}
public void call(final int id) {
Thread t = new Thread(new Task<String>() {
@Override
protected String call() throws Exception {
Thread.sleep(SLEEPTIME);
return null;
}
@Override
protected void succeeded() {
super.succeeded();
System.out.println("Next playing...");
if (id > LittleMediaScheduler.this.hArrL.size() - 1) {
return;
}
LittleMediaHelper next = LittleMediaScheduler.this.hArrL
.get(id);
Thread nextT = new Thread(next);
nextT.start();
}
});
t.start();
}
}
带有停止按钮的主类。如果没有mediaPlayer.pause(),玩家会以某种方式重复一步两次,尽管设置了新的开始结束端点。不知道是不是bug。
public class JavaFXMediaPlayer02 extends Application {
@Override
public void start(Stage stage) throws FileNotFoundException, IOException,
InterruptedException {
Media media = new Media("file:///C:/test.mp3");
final MediaPlayer mediaPlayer = new MediaPlayer(media);
LittleMediaHelper phase1 = new LittleMediaHelper(0, 1000, mediaPlayer,
0);
LittleMediaHelper phase2 = new LittleMediaHelper(50000, 55000,
mediaPlayer, 1);
LittleMediaHelper phase3 = new LittleMediaHelper(200000, 200500,
mediaPlayer, 2);
LittleMediaScheduler scheduler = new LittleMediaScheduler(phase1,
phase2, phase3);
scheduler.init();
Group g = new Group();
Button b = new Button("STOP");
b.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent arg0) {
mediaPlayer.pause();
mediaPlayer.stop();
}
});
g.getChildren().add(b);
Scene sc = new Scene(g);
stage.setScene(sc);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}