JavaFX setOnEndOfMedia на следующем MediaPlayer

У меня есть List<MediaPlayer>, который заполняется

private List<MediaPlayer> players() {

    for (String file : path.list((dir1, name) -> {
        if (name.endsWith(SUPPORTED_VIDEO_FILE_EXTENSIONS)){
            return true;
        }
        return false;
    })) {
        players.add(createPlayer(Paths.get(path + "/" + file).toUri().toString()));
        System.out.println(Paths.get(path + "/" + file).toUri().toString());
    }
    return players;
}

В моем случае размер List<MediaPlayer> равен 3. Тогда я использую его там.

if (currentNumOfVideo == -1) {
    currentNumOfVideo = 0;
}
mv = new MediaView();
MediaPlayer currentPlayer = players.get(currentNumOfVideo);
mv.setMediaPlayer(currentPlayer);
currentPlayer.play();

players.get(currentNumOfVideo).setOnEndOfMedia(() -> {
    players.get(currentNumOfVideo).stop();
    if (currentNumOfVideo < players.size()) {
        currentNumOfVideo += 1;
        mv.setMediaPlayer(players.get(currentNumOfVideo));
        players.get(currentNumOfVideo).play();
    } else {
        currentNumOfVideo = 0;
        mv.setMediaPlayer(players.get(currentNumOfVideo));
        players.get(currentNumOfVideo).play();
    }
});

Воспроизведение первого видео, когда оно заканчивается, начинается второе видео. После второго видео MediaPlayer останавливается и не воспроизводит третье видео.

Я понимаю, что из-за моего setOnEndOfMedia это только на первом MediaPlayer. Когда начинается второе видео, в нем нет setOnEndOfMedia. Как я могу setOnEndOfMedia на каждом видео в моем List<MediaPlayer>.


person Kzkovich    schedule 18.04.2020    source источник


Ответы (1)


Лично я бы не стал создавать все MediaPlayer экземпляры заранее. Вместо этого получите список из Media объектов или хотя бы URI, указывающих на носитель. Затем создайте метод, который отвечает за воспроизведение следующего видео по окончании текущего видео. Этот метод удалит старый MediaPlayer, создаст следующий MediaPlayer и настроит его для вызова того же метода по завершении. Например:

import java.util.List;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.stage.Stage;

public class Main extends Application {

  private MediaView mediaView;

  private List<Media> media;
  private int curIndex;

  @Override
  public void start(Stage primaryStage) throws Exception {
    media = ...; // get media from somewhere

    mediaView = new MediaView();
    primaryStage.setScene(new Scene(new StackPane(mediaView), 720, 480));
    primaryStage.show();

    playNextVideo();
  }

  private void playNextVideo() {
    disposePlayer();
    if (curIndex == media.size()) {
      return; // no more videos to play
    }

    MediaPlayer player = new MediaPlayer(media.get(curIndex++));
    player.setAutoPlay(true); // play ASAP
    player.setOnEndOfMedia(this::playNextVideo); // play next video when this one ends
    mediaView.setMediaPlayer(player);
  }

  private void disposePlayer() {
    MediaPlayer player = mediaView.getMediaPlayer();
    if (player != null) {
      player.dispose(); // release resources
    }
  }
}

Это может вызвать паузу между видео. Если это неприемлемо, вы можете создать следующий MediaPlayer заблаговременно, либо одновременно с текущим MediaPlayer, либо когда текущий игрок достигнет определенной отметки времени (например, за 10 секунд до конца). Но я бы все равно не стал создавать все MediaPlayer экземпляры заранее.

person Slaw    schedule 18.04.2020
comment
Я люблю вас! Вы осмыслили часы, которые я потратил, пытаясь решить эту проблему. - person Kzkovich; 19.04.2020