JavaFX时间轴播放滑块在异步时间点触发事件

时间:2016-11-07 08:44:24

标签: java asynchronous javafx timeline

我正在尝试实现一个自定义滑块,其上方有一个矩形条,其中的线条代表某些时间点的事件,如下图所示。它基本上是滑块上方的时间线,该事件描绘为垂直线。

enter image description here

该图显示了滑块的起点(t = 0)和结束点(t = x)之间的14条垂直线。每一行对应一个任意事件和一些上下文信息。

滑块将实时播放,即拇指将以实时速度沿其轨道移动。当滑块传递事件的指定时间时,它将在文本区域中打印事件的上下文信息。使用该图表,当前正在显示14秒事件的信息。

问题: 1.如何让拇指实时移动? 2.如何检测拇指已到达事件并因此触发在文本区域触发新输出的事件?

我的方法是处理所有事件并为每个事件创建一个计时器,以便在相关时间触发。这似乎相当不优雅。并且将来需要能够将拇指拖动到任何时间点,并且每次发生时都必须创建计时器事件,这似乎非常低效。

我正在使用JavaFX,所以我想尽可能地利用属性绑定。我在Java 8之前有很多经验,但这是我第一次愤怒地使用Java 8。

谢谢。

1 个答案:

答案 0 :(得分:1)

您可以使用Timeline中的Animation API来执行此操作。

简而言之:

public class TimelineEvent {
    private final Duration time ;
    private final String info ;
    public TimelineEvent(Duration time, String info) {
        this.time = time ;
        this.info = info ;
    }
    public Duration getTime() {
        return time ;
    }
    public String getInfo() {
        return info ;
    }
}
int maxSeconds = ... ;
TimelineEvent[] events = ... ; // populate array of events...
Slider slider = new Slider(0, maxSeconds, 0);
TextArea textArea = new TextArea();

// ...

Timeline timeline = new Timeline();
for (TimelineEvent event : events) {
    timeline.getKeyFrames().add(new KeyFrame(event.getTime(), 
        e -> textArea.setText(event.getInfo());
}

// make slider value change with timeline:
timeline.getKeyFrames().add(new KeyFrame(Duration.ZERO, 
    new KeyValue(slider.valueProperty(), 0)));
timeline.getKeyFrames().add(new KeyFrame(Duration.seconds(maxSeconds), 
    new KeyValue(slider.valueProperty(), maxSeconds)));

timeline.play();

另一种选择,如果用户要手动移动滑块,可能会更方便。 (以及动画制作),只是使用动画移动滑块,然后在滑块的值上使用侦听器或绑定:

int maxSeconds = ... ;
Slider slider = new Slider(0, maxSeconds, 0);
TextArea textArea = new TextArea();

Timeline timeline = new Timeline(
    new KeyFrame(Duration.ZERO, new KeyValue(slider.valueProperty(),0)),
    new KeyFrame(Duration.seconds(maxSeconds), new KeyValue(slider.valueProperty(),maxSeconds)));

textArea.textProperty().bind(Bindings.createStringBinding(
    () -> findInfoForTimepoint(slider.getValue()),
    slider.valueProperty()));

private String findInfoForTimepoint(double seconds) {
    // figure and return correct "info" for given time in seconds...
}