【问题标题】:How to print duration of media and style slider | JavaFX如何打印媒体和样式滑块的持续时间 | JavaFX
【发布时间】:2018-04-03 02:55:39
【问题描述】:

我正在为我的大学项目制作音乐播放器,但在使用 Sliders 时遇到了一些问题。

以下是我想用 Seeking Bar 做的事情:

  1. 如何设置搜索滑块的样式? (-fx-accent 不起作用)。
  2. 如何打印歌曲的总时长以及当前播放歌曲的时间。

下面是我用于 seekSlider 的代码:

package musicplayer;

import java.io.File;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ObservableValue;
import javafx.collections.MapChangeListener;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.stage.FileChooser;
import javafx.util.Duration;



public class FXMLDocumentController implements Initializable {

    @FXML
    private Button playbtn;
    @FXML
    private Button pausebtn;
    @FXML
    private Button stopbtn;
    @FXML
    private Button open;
    @FXML
    private Slider seekSlider;
    @FXML
    private Slider volumeSlider;
    @FXML
    private Label durationLabel;
    @FXML
    private Label musicBox;
    @FXML
    private Label playTime;
    @FXML
    private ImageView albumCover;
    @FXML
    private ImageView playbtnimg;

    @FXML
    private MediaView mv; 
    private MediaPlayer mp;
    private Media me;
    Double duration;
    File selectedFile = null;
    /**
     * Initializes the controller class.
     * @param e
     */

    //Open button code for choosing file through FileChooser
     public void open(ActionEvent e){


        FileChooser fc = new FileChooser();
        //Extension filter for showing mp3 and m4a files
        fc.getExtensionFilters().addAll(new
        FileChooser.ExtensionFilter("MP3", "*.mp3"),new
        FileChooser.ExtensionFilter("M4A", "*.m4a"));
        selectedFile = fc.showOpenDialog(null);

        //If runs when user selects a file
        if(selectedFile != null){

        String path = selectedFile.getAbsolutePath(); //gets the path of file
        if(mp!=null) //This if works when any song is playing
        {
            mp.stop(); //Stops the currently playing music

            //Change the album art to default.png
            File file = new File("src/musicplayer/default.png");
            Image image = new Image(file.toURI().toString());
            albumCover.setImage(image);
        }

        path = path.replace("\\","/");
        me = new Media(new File(path).toURI().toString());
        mp = new MediaPlayer(me);
        mv.setMediaPlayer(mp);
        //Code for Volume Slider 
        volumeSlider.setValue(0.7 * 100);
        volumeSlider.valueProperty().addListener((Observable observable) -> {
        mp.setVolume(volumeSlider.getValue()/100);
        });
        //Code for seeking bar

        seekSlider.maxProperty().bind(Bindings.createDoubleBinding(
            () -> mp.getTotalDuration().toSeconds(),
            mp.totalDurationProperty()));

        mp.currentTimeProperty().addListener((ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) -> {
            seekSlider.setValue(newValue.toSeconds());
        });

        seekSlider.setOnMouseClicked((MouseEvent event) -> {
            mp.seek(Duration.seconds(seekSlider.getValue()));
        });






        mp.play(); //Plays the selected song

        me.getMetadata().addListener(new MapChangeListener<String, Object>() {
        @Override
        public void onChanged(Change<? extends String, ? extends Object> ch) {
          if (ch.wasAdded()) {
            handleMetadata(ch.getKey(), ch.getValueAdded());
          }
        }

            private void handleMetadata(String key, Object value) {        
                if(key.equals("title")){   
                    musicBox.setText(value.toString());
                    }
                if(key.equals("image")){
                    albumCover.setImage((Image)value);
                    }
                }
            });
        }
    }
    public void play(ActionEvent e){
    mp.play();
    }

    public void pause(ActionEvent e){
    mp.pause();
    }

    public void stop(ActionEvent e){
    mp.stop();
    }


    @Override
    public void initialize(URL url, ResourceBundle rb) {


    }



}

我使用 playTime Label 来显示 totalDuration 和 durationLabel 来显示当前时间。 另外,检查 seekSlider 的代码,有时,它在拖动时无法正常工作。

【问题讨论】:

  • 首先将 seekSlider.setOnMouseClicked 替换为 seekSlider.valueProperty().addListener。滑块的控制不仅仅是鼠标点击。
  • @VGR 你能给我完整的代码吗?

标签: java javafx slider


【解决方案1】:

您可以创建一个 Label 并将其文本属性绑定到格式化 MediaPlayer 当前时间的绑定:

Label timeLabel = new Label();
timeLabel.textProperty().bind(
    Bindings.createStringBinding(() -> {
            Duration time = mp.getCurrentTime();
            return String.format("%4d:%02d:%04.1f",
                (int) time.toHours(),
                (int) time.toMinutes() % 60,
                time.toSeconds() % 3600);
        },
        mp.currentTimeProperty()));

请注意,您不应听鼠标输入,因为可以通过键盘和屏幕触摸来操作控件。最好改为听 value 属性:

Slider seekSlider = new Slider(0, 1, 0);
seekSlider.maxProperty().bind(
    Bindings.createDoubleBinding(
        () -> mp.getTotalDuration().toSeconds(),
        mp.totalDurationProperty()));

mp.currentTimeProperty().addListener((observable, oldValue, newValue) -> {
    seekSlider.setValue(newValue.toSeconds());
});

seekSlider.valueProperty().addListener((observable, oldValue, newValue) -> {
    mp.seek(Duration.seconds(newValue.doubleValue()));
});

请注意,MediaPlayer 的某些属性在首次构建时可能毫无意义,因为它会在后台加载媒体。例如,totalDuration 的初始值很可能是 Duration.UNKNOWN。

您可以通过将依赖于 MediaPlayer 的所有代码移动到 Runnable 中并将该 Runnable 传递给 setOnReady 来解决此问题:

Label timeLabel = new Label();
Slider seekSlider = new Slider();

mp.setOnReady(() -> {
    timeLabel.textProperty().bind(
        Bindings.createStringBinding(() -> {
                Duration time = mp.getCurrentTime();
                return String.format("%4d:%02d:%04.1f",
                    (int) time.toHours(),
                    (int) time.toMinutes() % 60,
                    time.toSeconds() % 3600);
            },
            mp.currentTimeProperty()));

    seekSlider.maxProperty().bind(
        Bindings.createDoubleBinding(
            () -> mp.getTotalDuration().toSeconds(),
            mp.totalDurationProperty()));

    mp.currentTimeProperty().addListener((observable, oldValue, newValue) -> {
        seekSlider.setValue(newValue.toSeconds());
    });

    seekSlider.valueProperty().addListener((observable, oldValue, newValue) -> {
        mp.seek(Duration.seconds(newValue.doubleValue()));
    });
});

【讨论】:

  • 当我使用你的代码作为听众时,歌曲不能正常播放了。以及是否有必要使用:Slider seekSlider = new Slider(0, 1, 0);
  • 其实你可以使用任何 Slider 构造函数,只要允许最小值有它的默认值,零。你能提供比“不再正常播放”更多的细节吗?你在看什么?您是在播放视频,还是只播放音频?
  • 我只是在播放音频 能否提供mail id、fb id 或其他信息,以便我可以将code 发送给您,我们可以更妥善地联系?
  • “不再正常播放”我的意思是每当我加载一首歌曲时,以前它一打开就开始播放但是使用你的代码后,它不会播放,只要我保持拖动滑块,它会播放鼠标放在滑块上的歌曲部分我一移开鼠标,它就会停止
  • 只有在已知媒体属性后,您才使用setOnReady 来初始化您的 Slider 和 Label,对吧?
猜你喜欢
  • 1970-01-01
  • 2014-07-08
  • 1970-01-01
  • 2014-11-26
  • 2017-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多