How to pause/resume a song in javafx?

2019-08-17 01:13发布

问题:

I'm making a playlist based mp3 player using javafx and I got everything working except how to pause/resume a song. I tried simply checking the player.Status()and using that but it didn't work so I stored the time of the song when pause()is clicked, in a Duration pausetime variable and it works that way but only once. What happens is: I click pause(), it works, click play(), it resumes the song but after that the pause button stops doing anything.

Btw I'm using two separate ToggleButton for pause and play because of the style I'm going for.

Here's the part of the code i'm talking about:

public void play(){
    if (player != null){
        player.stop();
    }
    if (pausebutton.isSelected()){
        pausebutton.setSelected(false);            //resume part
        slider.setValue(pausetime.toSeconds());
        play();
    }
    this.player = players.get(i);
    player.setStartTime(pausetime);
    player.play();
    slide(i);
    csong.setText(playlist.get(i).getName());
    player.setOnEndOfMedia(new Runnable(){
        @Override public void run(){
    if (shuffle.isSelected()){
        i = rand.nextInt(players.size() + 1);
    }
    else{
        i++;
    }
    if(loop.isSelected()){
    if (i == players.size()){
        i = 0;
    }}
    list.getSelectionModel().select(i);
    play();
            }
    });
}

public void pause(){
    player.pause();
    pausetime = player.getCurrentTime();
    playbutton.setSelected(false);
}

回答1:

I have created a very simple mp3 player, which has most (if not all) of the components said above.

  • It has play and pause toggle buttons, which do work ;)
  • It has labels updating the time elapsed for the song
  • It has a sliderbar, which can be used to move forward/backward. It automatically updates on song play.

Complete Code

import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.stage.Stage;
import javafx.util.Duration;

import java.text.DecimalFormat;

public class MediaPlayerSample extends Application {

    private MediaPlayer player;
    private final ToggleButton playButton = new ToggleButton("Play");
    private final ToggleButton pauseButton = new ToggleButton("Pause");
    private final ToggleGroup group = new ToggleGroup();
    private final Label totalDuration = new Label();
    private final Label currentDuration = new Label();
    private final DecimalFormat formatter = new DecimalFormat("00.00");
    private final SliderBar timeSlider = new SliderBar();
    private Duration totalTime;

    @Override
    public void start(Stage primaryStage)
    {
        //Add a scene
        VBox root = new VBox(10);
        root.setAlignment(Pos.CENTER);
        root.setStyle("-fx-background-color: ANTIQUEWHITE");

        HBox playPause = new HBox(playButton, pauseButton);
        HBox sliderBox = new HBox(timeSlider, currentDuration, totalDuration);

        HBox.setHgrow(sliderBox, Priority.ALWAYS);

        root.getChildren().addAll(sliderBox, playPause);
        Scene scene = new Scene(root, 300, 100);

        Media pick = new Media(getClass().getResource("/delete/abc/abc.mp3").toExternalForm());
        player = new MediaPlayer(pick);

        // Play the track and select the playButton
        player.play();
        playButton.setSelected(true);



        player.currentTimeProperty().addListener(new ChangeListener<Duration>() {
            @Override
            public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) {
                timeSlider
                        .sliderValueProperty()
                        .setValue(newValue.divide(totalTime.toMillis()).toMillis() * 100.0);
                currentDuration.setText(String.valueOf(formatter.format(newValue.toSeconds())));
            }
        });

        player.setOnReady(() -> {
            // Set the total duration
            totalTime = player.getMedia().getDuration();
            totalDuration.setText(" / " + String.valueOf(formatter.format(Math.floor(totalTime.toSeconds()))));
        });

        // Slider Binding
        timeSlider.sliderValueProperty().addListener((ov) -> {
            if (timeSlider.isTheValueChanging()) {
                if (null != player)
                    // multiply duration by percentage calculated by
                    // slider position
                    player.seek(totalTime.multiply(timeSlider
                            .sliderValueProperty().getValue() / 100.0));
                else
                    timeSlider.sliderValueProperty().setValue(0);
            }
        });


        //Applying Toggle Group to Buttons
        playButton.setToggleGroup(group);
        pauseButton.setToggleGroup(group);

        // Action for Buttons
        playButton.setOnAction(e -> {
            play();
        });

        pauseButton.setOnAction(e -> {
            pause();
        });

        //show the stage
        primaryStage.setTitle("Media Player");
        primaryStage.setScene(scene);
        primaryStage.show();


    }

    public void play(){
        player.play();
        playButton.setSelected(true);
    }

    public void pause(){
        player.pause();
        playButton.setSelected(false);
    }


    private class SliderBar extends StackPane {

        private Slider slider = new Slider();

        private ProgressBar progressBar = new ProgressBar();

        public SliderBar() {
            getChildren().addAll(progressBar, slider);
            bindValues();
        }
        private void bindValues(){
            progressBar.prefWidthProperty().bind(slider.widthProperty());
            progressBar.progressProperty().bind(slider.valueProperty().divide(100));
        }

        public DoubleProperty sliderValueProperty() {
            return slider.valueProperty();
        }

        public boolean isTheValueChanging() {
            return slider.isValueChanging();
        }
    }
    public static void main(String[] args) {
        launch(args);
    }
}

A simple look while it plays

You can style the mediaplayer using stylesheet. You can go through JavaFX CSS Reference for advanced topic on css.

For a mediaplayer with advanced features like:

  • Adding songs to a Playlist
  • Playing songs one after another
  • Drag and drop songs into mediaview

and much more, you can go visit this example.