我正在为我的大学项目制作一个音乐播放器,并面对Sliders的一些问题。
以下是我用于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的代码,有时,拖动时它无法正常工作。
答案 0 :(得分:1)
您可以创建Label并将其text属性绑定到格式化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()));
});
});