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

问题描述:

我试图实现一个自定义滑块上面的矩形条带有代表事件在某些时间点的事件,如下图所示。它基本上是一个滑块上方的时间线,该事件描述为垂直线。JavaFX时间线播放滑块触发事件在异步时间点

enter image description here

图显示在滑块的开始(t = 0时)和终点(T = X)14条之间的垂直线。每行对应一个任意事件和一些上下文信息。

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

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

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

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

谢谢。

您可以使用Animation APITimeline进行此操作。

简言之:

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... 
} 
+0

感谢您的建议James_D。第一个是非常优雅的地方,每个事件都设置为一个KeyFrame,当相应的时间流逝时触发。第二种方法也很好,但是,bind语句会在每个滑块值更改上运行,这意味着findInfoForTimepoint()会运行很多次,这是不可取的。 所以我倾向于第一个建议。然而,我试图修改它在播放过程中移动拇指,但由于某些原因,我不能。有没有办法将拇指拉回到某一点,然后继续播放,而KeyFrame事件仍然有效? – emjay