2013-10-23 60 views
3

我有一个应用程序具有带有一些双精度值的组合框。用户可以选择任何值。该应用程序附有一个“TimeLine”,它将在控制台上打印语句。下面是sscce。应该发生的是,应该打印从组合框中选择的选项的文本。请建议。JavaFX:将时间轴的持续时间绑定到属性

package just.to.test; 

import javafx.animation.KeyFrame; 
import javafx.animation.Timeline; 
import javafx.application.Application; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.event.ActionEvent; 
import javafx.event.EventHandler; 
import javafx.scene.Group; 
import javafx.scene.Scene; 
import javafx.scene.control.ComboBox; 
import javafx.stage.Stage; 
import javafx.util.Duration; 

public class TimerSample extends Application { 
    public static void main(String[] args) { 
     Application.launch(args); 
    } 

    @Override 
    public void start(Stage primaryStage) { 
     primaryStage.setTitle("Text Fonts"); 

     Group g = new Group(); 
     Scene scene = new Scene(g, 150, 100); 

     ObservableList<Double> data = FXCollections.observableArrayList(); 

     data.add(5.0); 
     data.add(10.0); 
     data.add(15.0); 
     data.add(20.0); 

     ComboBox<Double> timeOptions = new ComboBox<Double>(data); 
     timeOptions.getSelectionModel().selectFirst(); 

     g.getChildren().addAll(timeOptions); 

     primaryStage.setScene(scene); 
     primaryStage.show(); 

     final double timerInterval = timeOptions.getSelectionModel().getSelectedItem(); 

     KeyFrame keyFrame = new KeyFrame(Duration.seconds(timerInterval), 
      new EventHandler<ActionEvent>() { 
       @Override 
       public void handle(ActionEvent event) { 
        System.out.println("This is called every " 
         + timerInterval + " seconds"); 
       } 
      }); 

     Timeline timerThread = new Timeline(keyFrame); 
     timerThread.setCycleCount(Timeline.INDEFINITE); 
     timerThread.play(); 
    } 
} 

回答

7

不能在时间轴的时间绑定到一个属性,因为一个关键帧的时间轴中的持续时间不是一个属性,你只能绑定属性的属性。

你需要做的,而不是什么是监听的组合框的值发生变化,并触发当用户选择一个新的持续时间创建新的持续时间新的关键帧。您也无法修改正在运行的时间轴的关键帧,因此必须在设置时间轴的新关键帧之前停止时间轴,然后在新的关键帧设置完成后开始时间轴。

示例代码

import javafx.animation.*; 
import javafx.application.Application; 
import javafx.beans.value.*; 
import javafx.collections.*; 
import javafx.event.*; 
import javafx.scene.*; 
import javafx.scene.control.ComboBox; 
import javafx.stage.Stage; 
import javafx.util.Duration; 

public class TimerSample extends Application { 
    public static void main(String[] args) { 
     Application.launch(args); 
    } 

    @Override 
    public void start(Stage stage) { 
     Group g = new Group(); 
     Scene scene = new Scene(g, 150, 100); 

     ComboBox<Double> timerOptions = createTimerOptions(
       0.5, 1.0, 1.5, 2.0 
     ); 
     g.getChildren().addAll(timerOptions); 

     createTimer(timerOptions); 

     stage.setScene(scene); 
     stage.show(); 
    } 

    private ComboBox<Double> createTimerOptions(double... options) { 
     ObservableList<Double> data = FXCollections.observableArrayList(); 

     for (Double option: options) { 
      data.add(option); 
     } 

     return new ComboBox<Double>(data); 
    } 

    private void createTimer(ComboBox<Double> timeOptions) { 
     final Timeline timer = new Timeline(); 
     timer.setCycleCount(Timeline.INDEFINITE); 

     timeOptions.valueProperty().addListener(new ChangeListener<Double>() { 
      @Override 
      public void changed(ObservableValue<? extends Double> observable, Double oldValue, Double newValue) { 
       resetTimer(timer, newValue); 
      } 
     }); 

     timeOptions.getSelectionModel().selectFirst(); 
    } 

    private void resetTimer(Timeline timer, final double timerInterval) { 
     KeyFrame keyFrame = new KeyFrame(
      Duration.seconds(timerInterval), 
      new EventHandler<ActionEvent>() { 
       @Override 
       public void handle(ActionEvent event) { 
        System.out.println(
          "This is called every " 
            + timerInterval 
            + " seconds" 
        ); 
       } 
      } 
     ); 

     timer.stop(); 
     timer.getKeyFrames().setAll(
       keyFrame 
     ); 
     timer.play(); 
    } 
} 

只是想知道,在性能方面是由于添加新的关键帧,在组合框的值的每一个变化要重得多。

在这种情况下,不要过于担心性能 - 这是一种高效的操作。

没有比因为关键帧immutable objects创造新的关键帧没有其他解决办法。

您可以先构建关键帧,或者将它们放在类似于LRU cache的东西中,就像您懒惰地构建它们一样,但总体而言,所涉及的额外复杂性几乎肯定不值得。

+0

的伟大工程。谢谢。但只是想知道性能是否明智,因为随着组合框值的每次变化都添加一个新的关键帧。 – Aspirant

+0

根据其他问题更新了答案。 – jewelsea

+0

'rateProperty()'不会更清洁吗? – Mordechai

2

所有动画有rateProperty()它可以在一个正在运行的动画来改变!

这似乎是一个更清洁的解决方案:

private void createTimer(ComboBox<Double> timeOptions) { 
    Timeline timer = new Timeline(
      new KeyFrame(Duration.seconds(1), 
      evt-> System.out.println(
         "This is called every " 
           + timeOptions.getValue() 
           + " seconds" 
       )); 

    timer.setCycleCount(Timeline.INDEFINITE); 
    timer.rateProperty() 
     .bind(new SimpleDoubleProperty(1.0) 
     .divide(timeOptions.valueProperty())); 

    timeOptions.getSelectionModel().selectFirst(); 
}