如何在JavaFx音乐播放器中获得歌曲持续时间



我使用JavaFX创建了一个音乐播放器。然而,我不明白我怎么能知道我目前正在播放的歌曲的持续时间。

编辑: 我在代码中添加了以下几行,现在歌曲的持续时间是可见的。但是,当我播放下一首歌曲时,歌曲的持续时间是不可见的。以下是我添加到代码中的行:

mediaPlayer.currentTimeProperty().addListener(new TimeListener());  
TimeListener = new ChangeListener<Duration>() 
{
@Override public void changed(ObservableValue<? extends Duration> o, Duration oldVal, Duration newVal) 
{
//now newVal is of Duration class
}
};
}

public class TimeListener implements ChangeListener {
public void changed(ObservableValue o, Object oldVal, Object newVal) {
//Update time display with MediaPlayer's current time:
playTime.setText(newVal.toString());
}
}

这是我创建音乐播放器的代码:

public class MusicController implements Initializable 
{
@FXML
private ImageView trackLogo;
@FXML
private Button next, previous, pause, play, reset;
@FXML
private Slider VolumeSlider;    
@FXML
private AnchorPane Panel;   
@FXML
private Label playTime, appTitle, songTitle;    
@FXML
private ProgressBar songProgressBar;
@FXML
private Media media;
private MediaPlayer mediaPlayer;
private File directory;
private File [] files;
private ArrayList<File> songs;  
private int songNumber; 
private Timer timer;
private TimerTask task;
private boolean running;
private ChangeListener<Duration> TimeListener;

@Override
public void initialize(URL url, ResourceBundle rb) 
{
songs = new ArrayList<File>();      
directory = new File("music");      
files = directory.listFiles();      
if(files!=null) 
{
for(File file : files)
{
songs.add(file);
System.out.println(file);
}
}       
media = new Media(songs.get(songNumber).toURI().toString());
mediaPlayer = new MediaPlayer(media);
mediaPlayer.currentTimeProperty().addListener(new TimeListener());      
songTitle.setText(songs.get(songNumber).getName());
VolumeSlider.valueProperty().addListener(new ChangeListener<Number>()
{
public void changed(ObservableValue<? extends Number> arg0, Number arg1, Number arg2) 
{       
mediaPlayer.setVolume(VolumeSlider.getValue() * 0.01);  
}
});

TimeListener = new ChangeListener<Duration>() 
{
@Override public void changed(ObservableValue<? extends Duration> o, Duration oldVal, Duration newVal) 
{
//now newVal is of Duration class
}
};
}

public class TimeListener implements ChangeListener {
public void changed(ObservableValue o, Object oldVal, Object newVal) {
//Update time display with MediaPlayer's current time:
playTime.setText(newVal.toString());
}
}

public void playMedia() 
{   
beginTimer();
mediaPlayer.setVolume(VolumeSlider.getValue() * 0.01);
mediaPlayer.play();
}

public void pauseMedia() 
{   
cancelTimer();
mediaPlayer.pause();
}
public void resetMedia() 
{   
songProgressBar.setProgress(0);
mediaPlayer.seek(Duration.seconds(0));
}

public void previousMedia() 
{   
if (songNumber > 0)
{
songNumber--;
mediaPlayer.stop();

if(running)
{
cancelTimer();
}

media = new Media(songs.get(songNumber).toURI().toString());
mediaPlayer = new MediaPlayer(media);
songTitle.setText(songs.get(songNumber).getName());
playMedia();
}
else
{
songNumber = songs.size() - 1;
mediaPlayer.stop();

if(running)
{
cancelTimer();
}


media = new Media(songs.get(songNumber).toURI().toString());
mediaPlayer = new MediaPlayer(media);
songTitle.setText(songs.get(songNumber).getName());
playMedia();
}
}

public void nextMedia() 
{   
if (songNumber < songs.size() - 1)
{
songNumber++;
mediaPlayer.stop();

if(running)
{
cancelTimer();
}

media = new Media(songs.get(songNumber).toURI().toString());
mediaPlayer = new MediaPlayer(media);
songTitle.setText(songs.get(songNumber).getName());
playMedia();
}
else
{
songNumber = 0;
mediaPlayer.stop();

if(running)
{
cancelTimer();
}
media = new Media(songs.get(songNumber).toURI().toString());
mediaPlayer = new MediaPlayer(media);
songTitle.setText(songs.get(songNumber).getName());
playMedia();
}
}


public void beginTimer() 
{   
timer = new Timer();
task = new TimerTask()
{   
public void run() 
{
running = true;
double current = mediaPlayer.getCurrentTime().toSeconds();
double end = media.getDuration().toSeconds();
System.out.println(current/end);
songProgressBar.setProgress(current/end);

if (current/end ==1)
{
cancelTimer();
}

}
};
timer.scheduleAtFixedRate(task, 0, 1000);
}

public void cancelTimer() 
{   
running = false;
timer.cancel();
}

}

我已尝试阅读Oracle文档(https://docs.oracle.com/javase/8/javafx/media-tutorial/playercontrol.htm)还有这个youtube视频(https://www.youtube.com/watch?v=-D2OIekCKes(来创建音乐播放器。

如果有任何帮助,我将不胜感激。提前感谢!

对于这样的事情,不应该使用Timer或一般的线程。MediaPlayer的属性是可观察的,因此您应该向它们添加监听器,或者将UI属性绑定到它们。以下是将ProgressBar的progress属性绑定到播放器的示例:

progressBar.progressProperty().bind(
Bindings.createDoubleBinding(() -> {
Duration current = mediaPlayer.getCurrentTime();
Duration total = mediaPlayer.getCycleDuration();
return current.toMilli() / total.toMillis();
},
mediaPlayer.currentTimeProperty(),
mediaPlayer.cycleDurationProperty())
);

以上使用了Bindings#createDoubleBinding(Callable,Observable…(和lambda表达式

每次创建新的MediaPlayer时,您都需要执行上述操作,但除此之外,这将处理保持进度条最新的问题。您还可以对以可读格式显示当前时间和总时间的标签执行类似操作。

此外,不需要在volumeSlider中添加侦听器,您可以执行以下操作:

mediaPlayer.volumeProperty().bind(volumeSlider.valueProperty());

有关详细信息,请参阅使用JavaFX属性和绑定。


顺便说一句,你不仅不应该在这里使用Timer,而且你使用它的方式是不正确的。在JavaFX中,有一个名为JavaFX应用程序线程的特殊线程。只有该线程应该直接或间接地与UI交互。使用任何其他线程与UI交互都是破坏代码,并可能导致未定义的行为——JavaFX不是线程安全的。

您可以使用Platform#runLater(Runnable)在FX线程上安排操作。

相关内容

  • 没有找到相关文章

最新更新