我有一个名为TimeElapsed
的自定义类(不可变)。 TimeElapsed
具有一个接受Duration
(这是JavaFx MediaPlayer
中用来跟踪时间的类型)的构造函数。然后,构造函数将Duration
转换为TimeElapsed
。
问题是我有一个需要返回TimeElapsed
ObservableValue
的函数。我需要做的是这样的事情:
new Binding<TimeElapsed>() {
{
super.bind(player.duration())
}
@Override
protected TimeElapsed computeValue() {
return new TimeElapsed(player.duration());
}
}
但是由于某种原因,没有
Binding
泛型,因此只能使用DoubleBinding
和类似的方法来实现,在这种情况下,您可以计算值但不能选择类型。所以我该怎么做? 最佳答案
使用 ObjectBinding<TimeElapsed>
的样本解决方案。
关键方法
/* @return an ObjectBinding of immutable TimeElapsed objects for the player */
private ObjectBinding<TimeElapsed> createElapsedBindingByBindingsAPI(
final MediaPlayer player
) {
return Bindings.createObjectBinding(
new Callable<TimeElapsed>() {
@Override
public TimeElapsed call() throws Exception {
return new TimeElapsed(player.getCurrentTime());
}
},
player.currentTimeProperty()
);
}
完整的可执行文件示例
更改示例中的
MEDIA_PATH
以匹配您所需的媒体。import javafx.application.Application;
import javafx.beans.binding.*;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.media.*;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.io.File;
import java.net.MalformedURLException;
import java.util.concurrent.Callable;
/** Displays progress (time elapsed in seconds) of playing a media file. */
public class TimeElapsedBinding extends Application {
private static final String MEDIA_PATH =
"C:\\Users\\Public\\Music\\Sample Music\\Dillon - Thirteen Thirtyfive.mp3";
public static void main(String[] args) { launch(args); }
@Override public void start(Stage stage) throws Exception {
final MediaView mediaView = createMediaView();
final MediaPlayer player = mediaView.getMediaPlayer();
final Label elapsedLabel = new Label();
ObjectBinding<TimeElapsed> elapsedBinding =
createElapsedBindingByBindingsAPI(player);
StringBinding elapsedStringBinding =
createStringBindingByBindingsAPI(elapsedBinding);
elapsedLabel.textProperty().bind(
elapsedStringBinding
);
StackPane layout = new StackPane();
layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 20px;");
layout.getChildren().setAll(
mediaView,
elapsedLabel
);
stage.setScene(new Scene(layout));
stage.show();
}
/* @return an ObjectBinding of immutable TimeElapsed objects for the player */
private ObjectBinding<TimeElapsed> createElapsedBindingByBindingsAPI(
final MediaPlayer player
) {
return Bindings.createObjectBinding(
new Callable<TimeElapsed>() {
@Override
public TimeElapsed call() throws Exception {
return new TimeElapsed(player.getCurrentTime());
}
},
player.currentTimeProperty()
);
}
/* @return a string binding to an ObjectBinding of immutable TimeElapsed objects */
private StringBinding createStringBindingByBindingsAPI(
final ObjectBinding<TimeElapsed> elapsedBinding
) {
return Bindings.createStringBinding(
new Callable<String>() {
@Override
public String call() throws Exception {
return String.format(
"%.0f",
elapsedBinding.getValue().getElapsed()
);
}
},
elapsedBinding
);
}
/* @Return a new MediaView from a predefined MEDIA_PATH string */
private MediaView createMediaView() throws MalformedURLException {
String mediaURI = new File(MEDIA_PATH).toURI().toURL().toExternalForm();
Media media = new Media(mediaURI);
MediaPlayer player = new MediaPlayer(media);
MediaView mediaView = new MediaView(player);
player.play();
return mediaView;
}
/** immutable TimeElapsed class. */
class TimeElapsed {
private final double elapsed;
TimeElapsed(Duration duration) {
elapsed = duration.toSeconds();
}
public double getElapsed() {
return elapsed;
}
}
}
上面提供的只是作为适合在ObjectBinding中使用不可变对象的问题框架的示例,而不是作为跟踪播放媒体进度的最有效方法。
替代实施
无需在ObjectBinding中使用不可变对象,我将直接监视MediaPlayer的progress属性,类似于下面的代码:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.StackPane;
import javafx.scene.media.*;
import javafx.stage.Stage;
import java.io.File;
import java.net.MalformedURLException;
public class MediaProgressMonitoring extends Application {
private static final String MEDIA_PATH = "C:\\Users\\Public\\Music\\Sample Music\\Dillon - Thirteen Thirtyfive.mp3";
public static void main(String[] args) { launch(args); }
@Override public void start(Stage stage) throws Exception {
final MediaView mediaView = createMediaView();
final MediaPlayer player = mediaView.getMediaPlayer();
final ProgressBar progress = new ProgressBar(0);
progress.setPrefWidth(800);
player.currentTimeProperty().addListener((observable) ->
progress.setProgress(
player.getCurrentTime().toMillis() /
player.getTotalDuration().toMillis()
)
);
StackPane layout = new StackPane();
layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 20px;");
layout.getChildren().setAll(
mediaView,
progress
);
stage.setScene(new Scene(layout));
stage.show();
}
private MediaView createMediaView() throws MalformedURLException {
String mediaURI = new File(MEDIA_PATH).toURI().toURL().toExternalForm();
Media media = new Media(mediaURI);
MediaPlayer player = new MediaPlayer(media);
MediaView mediaView = new MediaView(player);
player.play();
return mediaView;
}
}