I have created a media player method is javafx which is called upon startup (below is the media player). My problem is that this pauses whenever I interact with a scroll pane by dragging or by zooming the player pauses and does not start again. Why is this the case and how may I fix this(included full application if you would to try it).
Method(Live code)
private static void MusicPlayer() {
if(musicList.peek() == null)
{
return;
}
MediaPlayer mediaPlayer = new MediaPlayer(new Media(new File(musicList.poll()).toURI().toString()));
mediaPlayer.setOnReady(() -> {
mediaPlayer.play();
mediaPlayer.setOnEndOfMedia(() -> {
mediaPlayer.dispose();
MusicPlayer();
});
});
}
Minimal
package minimalist;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.stream.Collectors;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.stage.Stage;
public class Minimal extends Application{
private static Queue<String> musicList = new LinkedList<String>();
public static void main(String[] args) throws IOException {
List<String> result = Files.find(Paths.get(".\\music"), 100,
(p, a) -> p.toString().toLowerCase().endsWith(".mp3"))
.map(path -> path.toString())
.collect(Collectors.toList());
for(int a = 0; a < result.size(); a++)
{
musicList.add(result.get(a));
}
MusicPlayer();
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
ScrollPane scrollpane = new ScrollPane();
Image image = new Image("https://upload.wikimedia.org/wikipedia/commons/7/70/Kusatma_Zonaro.jpg");
ImageView imageView = new ImageView(image);
scrollpane.setContent(imageView);
scrollpane.setPannable(true);
Scene scene = new Scene(new StackPane(scrollpane));
primaryStage.setScene(scene);
primaryStage.setFullScreen(true);
primaryStage.show();
}
private static void MusicPlayer() {
if(musicList.peek() == null)
{
return;
}
MediaPlayer mediaPlayer = new MediaPlayer(new Media(new File(musicList.poll()).toURI().toString()));
mediaPlayer.setOnReady(() -> {
mediaPlayer.play();
mediaPlayer.setOnEndOfMedia(() -> {
mediaPlayer.dispose();
MusicPlayer();
});
});
}
}
This all seems to behave in something of a fragile manner.
I would not recommend launching the media player from the main
method. The documentation is a bit lacking on threading policy for MediaPlayer
, but since you are launching a regular JavaFX application it would seem sensible to follow the usual rules and only call methods on it from the JavaFX Application Thread. On my system, I was unable to get any music playing the way you had it set up.
I also had sporadic issues getting it to start playing after changing that; I guessed that maybe I was leaving system resources tied up after exiting, so I modified the code to ensure the player was disposed when the application ended. After both those changes, it behaved as expected. At no point though did I have any issues associated with user input; my guess is that these are caused by launching the media player from the main thread instead of from the FX Application Thread, and are probably system-dependent.
Here's the code that worked fine for me. I also cleaned up some of the redundancy in your code (iterating through Path
s to convert them to String
s which you then convert back to File
s so you can convert to a string representation of a URL seems somewhat circuitous; you also create a completely unnecessary list in that process, etc) and renamed things so that it abides by proper naming conventations):
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.LinkedList;
import java.util.Queue;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.stage.Stage;
public class Minimal extends Application{
private Queue<Path> musicList = new LinkedList<>();
private MediaPlayer mediaPlayer ;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
// Everyone should have this album. Edit the path if your musical taste is poor.
Files.find(Paths.get(System.getProperty("user.home"),"Music/iTunes/iTunes Media/Music/Thievery Corporation/Saudade/"), 100,
(p, a) -> p.toString().toLowerCase().endsWith(".m4a"))
.forEach(musicList::add);
playMusic();
ScrollPane scrollpane = new ScrollPane();
Image image = new Image("https://upload.wikimedia.org/wikipedia/commons/7/70/Kusatma_Zonaro.jpg");
ImageView imageView = new ImageView(image);
scrollpane.setContent(imageView);
scrollpane.setPannable(true);
Scene scene = new Scene(new StackPane(scrollpane));
primaryStage.setScene(scene);
primaryStage.setFullScreen(true);
primaryStage.show();
}
@Override
public void stop() {
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.dispose();
}
}
private void playMusic() {
if(musicList.peek() == null)
{
return;
}
mediaPlayer = new MediaPlayer(new Media(musicList.poll().toUri().toString()));
mediaPlayer.setOnReady(() -> {
mediaPlayer.play();
mediaPlayer.setOnEndOfMedia(() -> {
mediaPlayer.dispose();
playMusic();
});
});
}
}