2016-08-04 8 views
1

Ich versuche, ein System zu erstellen, in dem eine Zeitleiste verwendet wird, um die Dauer einer Minute aufzuzeichnen. In diesem Fall möchte ich, dass die Zeitleiste pro Sekunde hochzählt und die Fortschrittsleiste dies bis zu 1 Minute vor dem Aufrufen einer Aktion und dem Zurücksetzen der Zeitleiste aufzeichnet.Wie bekomme ich JavaFX Timeline um Sekunden zu erhöhen und an eine Progressbar zu binden?

Ich habe die Anzahl der Zyklen auf unbestimmte Zeit festgelegt, so dass der Timeline-Zyklus nie aufhört. Ich habe auch versucht, die Progressbar-Eigenschaft an die Zeitleiste zu binden, aber es erfordert einen Observablevalue, um dies zu tun, die timeline#getTotalDuration nicht bietet.

Ich habe versucht, das Programm ohne die Bindung an einem separaten Thread ausgeführt wird:

new Thread(new Task<Void>() { 
      @Override 
      protected Void call() throws Exception { 
       while(true){ 
        System.out.printf("s:\t%f\n",timeline.getTotalDuration().toSeconds()); 
        Thread.sleep(1000); 
       } 
      } 
}).start(); 

jedoch läuft dies nicht den Timer pro Sekunde nicht erhöht, sondern geht nur durch alle Zyklen auf einmal. Da der eingestellte cycleCount INDEFINITE ist, ist das Ergebnis #totalDurationinfinite.

Wie würde ich die Timeline im Sekundentakt arbeiten lassen und wie würde ich die Dauer an die Progressbar binden können, bis sie 100% erreicht, so dass meine spezielle Aktion aufgerufen werden kann?

Antwort

4

Wenn Sie nur die Fortschrittsbalken wollen von Null auf Voll über den Verlauf einer Minute wiederholt erhöhen und Code ausführen, wenn das Ende jeder Minute erreicht, alles was Sie brauchen:

ProgressBar progress = new ProgressBar(); 
    Timeline timeline = new Timeline(
     new KeyFrame(Duration.ZERO, new KeyValue(progress.progressProperty(), 0)), 
     new KeyFrame(Duration.minutes(1), e-> { 
      // do anything you need here on completion... 
      System.out.println("Minute over"); 
     }, new KeyValue(progress.progressProperty(), 1))  
    ); 
    timeline.setCycleCount(Animation.INDEFINITE); 
    timeline.play(); 

That erzeugt einen "analogen" Effekt für den Fortschrittsbalken, dh er erhöht sich nicht in jeder Sekunde, sondern gleichmäßig über die ganze Minute.

Wenn Sie jede Sekunde erhöhen möchte wirklich schrittweise, eine IntegerProperty verwenden, um die Anzahl der Sekunden zu repräsentieren, und binden den Fortschritt Eigenschaft des Fortschrittsbalken, um es:

ProgressBar progress = new ProgressBar(); 
    IntegerProperty seconds = new SimpleIntegerProperty(); 
    progress.progressProperty().bind(seconds.divide(60.0)); 
    Timeline timeline = new Timeline(
     new KeyFrame(Duration.ZERO, new KeyValue(seconds, 0)), 
     new KeyFrame(Duration.minutes(1), e-> { 
      // do anything you need here on completion... 
      System.out.println("Minute over"); 
     }, new KeyValue(seconds, 60)) 
    ); 
    timeline.setCycleCount(Animation.INDEFINITE); 
    timeline.play(); 

Der hier ist, dass die IntegerProperty interpoliert wird zwischen 0 und 60, akzeptiert aber nur ganzzahlige Werte (dh es wird den interpolierten Wert auf int gekürzt).

Hier ist ein SSCCE mit der zweiten Version:

import javafx.animation.Animation; 
import javafx.animation.KeyFrame; 
import javafx.animation.KeyValue; 
import javafx.animation.Timeline; 
import javafx.application.Application; 
import javafx.beans.property.IntegerProperty; 
import javafx.beans.property.SimpleIntegerProperty; 
import javafx.geometry.Insets; 
import javafx.scene.Scene; 
import javafx.scene.control.ProgressBar; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage; 
import javafx.util.Duration; 

public class OneMinuteTimer extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     ProgressBar progress = new ProgressBar(); 
     progress.setMinWidth(200); 
     progress.setMaxWidth(Double.MAX_VALUE); 
     IntegerProperty seconds = new SimpleIntegerProperty(); 
     progress.progressProperty().bind(seconds.divide(60.0)); 
     Timeline timeline = new Timeline(
      new KeyFrame(Duration.ZERO, new KeyValue(seconds, 0)), 
      new KeyFrame(Duration.minutes(1), e-> { 
       // do anything you need here on completion... 
       System.out.println("Minute over"); 
      }, new KeyValue(seconds, 60)) 
     ); 
     timeline.setCycleCount(Animation.INDEFINITE); 
     timeline.play(); 

     StackPane root = new StackPane(progress); 
     root.setPadding(new Insets(20)); 
     primaryStage.setScene(new Scene(root)); 
     primaryStage.show(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
}