Java Reference
In-Depth Information
#playPauseButton:hover, #seekEndButton:hover, #seekStartButton:hover {
-fx-background-color: rgb(255, 255, 255, 0.1);
}
The logic that controls the actual seek operation is encapsulated in the
seekAndUpdatePosition
method.
Remember that the
seek
method has no effect if the player is in the
STOPPED
state. If that is the case, we need to call
the
pause
method before the
seek
method is called or the seek will not work. Also note that after
seek
is called, we
manually update the position slider if the
MediaPlayer
is not playing. This is necessary because the
MediaPlayer
's
currentTime
property is not updated automatically by the call to seek. If the
MediaPlayer
is playing, this is not
noticeable because playback will immediately continue from the new seek position, causing the
currentTime
to
be quickly updated as well. On the other hand, if the
MediaPlayer
is not playing then the
currentTime
will not be
updated, causing the position slider (which listens to and displays
currentTime
updates) to become out of sync with
the new playback position. This is noticeable the next time the play button is pressed; the position slider will suddenly
skip ahead or back to the position of the last seek.
This discussion has led nicely to the third control in the audio player that makes use of the seek function: the
aforementioned position slider. The position slider does double duty: It displays the
currentTime
value but can
also be dragged to a new position, resulting in a call to the
seek
method. As you can probably guess, there are some
subtleties to account for when getting this to work properly. Listing 9-19 shows the code required to implement the
first part of this functionality: displaying the
currentTime
value on the position slider.
Listing 9-19.
Displaying the Value of
currentTime
on the Position Slider
private class CurrentTimeListener implements InvalidationListener {
@Override
public void invalidated(Observable observable) {
Platform.runLater(() -> {
final MediaPlayer mediaPlayer = songModel.getMediaPlayer();
final Duration currentTime = mediaPlayer.getCurrentTime();
currentTimeLabel.setText(formatDuration(currentTime));
updatePositionSlider(currentTime);
});
}
}
private void updatePositionSlider(Duration currentTime) {
if (positionSlider.isValueChanging())
return;
final MediaPlayer mediaPlayer = songModel.getMediaPlayer();
final Duration total = mediaPlayer.getTotalDuration();
if (total == null || currentTime == null) {
positionSlider.setValue(0);
} else {
positionSlider.setValue(currentTime.toMillis() / total.toMillis());
}
}
Like the
status
property,
MediaPlayer
's
currentTime
property is updated on a different thread than the main
JavaFX application thread. Therefore we cannot bind to it directly and must instead attach an
InvalidationListener
that utilizes
Platform.runLater
to perform updates to live scene graph nodes such as the position slider. Listing 9-19
shows the implementation of the
CurrentTimeListener
inner class that accomplishes this for us. The
Runnable
's
Search WWH ::
Custom Search