Reputation: 11
I'm trying to display a timer which counts and displays seconds in a label after clicking the start button but I'm not getting desired output.Here's my code of the controller and FXML file...
public class FXMLDocumentController implements Initializable {
@FXML
private static final Integer STARTTIME = 0;
private Timeline timeline;
private Label timerLabel = new Label();
private IntegerProperty timeSeconds = new SimpleIntegerProperty(STARTTIME);
Button button = new Button();
public void handle(ActionEvent event) {
if (timeline != null) {
timeline.stop();
}
timeSeconds.set(STARTTIME);
timeline = new Timeline();
timeline.getKeyFrames().add(new KeyFrame(Duration.seconds(STARTTIME+1),
new KeyValue(timeSeconds, 0)));
timeline.playFromStart();
timerLabel.textProperty().bind(timeSeconds.asString());
}
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
and this is my FXML code..
<Button fx:id="button" layoutX="120.0" layoutY="40.0"
mnemonicParsing="false" text="Start Timmer" onAction="#handle" />
<Label layoutX="132.0" layoutY="92.0" prefHeight="17.0" prefWidth="65.0"
textFill="#f20b0b">
<font>
<Font size="24.0" />
</font>
</Label>
Upvotes: 1
Views: 3050
Reputation: 82491
You don't use Timeline
correctly.
The duration of the KeyFrame
is the offset from the start of the animation when the update is executed. Multiple clicks on your button all add KeyFrame
s that run 1 second after the start of the animation.
Furthermore using KeyValue
interpolates the value from the current value to the value passed to KeyValue
. This makes little sense, if the new value is the same as the old value.
You should instead use a EventHandler<ActionEvent>
to update the property.
Furthermore the button
field should be injected by FXMLLoader
. This requires the field to be public
or annotated with @FXML
.
<Button fx:id="button" layoutX="120.0" layoutY="40.0"
mnemonicParsing="false" text="Start Timmer" onAction="#handle" />
<Label fx:id="timerLabel" layoutX="132.0" layoutY="92.0" prefHeight="17.0" prefWidth="65.0"
textFill="#f20b0b">
<font>
<Font size="24.0" />
</font>
</Label>
public class FXMLDocumentController implements Initializable {
private static final int STARTTIME = 0;
private Timeline timeline;
private final IntegerProperty timeSeconds = new SimpleIntegerProperty(STARTTIME);
@FXML
private Label timerLabel;
@FXML
private Button button;
private void updateTime() {
// increment seconds
int seconds = timeSeconds.get();
timeSeconds.set(seconds+1);
}
public void handle(ActionEvent event) {
button.setDisable(true); // prevent starting multiple times
timeline = new Timeline(new KeyFrame(Duration.seconds(1), evt -> updateTime()));
timeline.setCycleCount(Animation.INDEFINITE); // repeat over and over again
timeSeconds.set(STARTTIME);
timeline.play();
}
public void initialize(URL url, ResourceBundle rb) {
// TODO
timerLabel.textProperty().bind(timeSeconds.asString());
}
}
Upvotes: 3