我有一个名为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
和类似的东西执行此操作,您可以在其中计算值但无法选择类型。那么,我该怎么办?
答案 0 :(得分:7)
使用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;
}
}