Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaFX stopwatch timer

This is a class for a simple stopwatch for JavaFX, style the Label object as desired

package aaa;

import java.text.SimpleDateFormat;
import java.util.Date;
import javafx.beans.property.SimpleStringProperty;

/**
 *
 * @author D07114915
 */
public class KTimer extends Thread {

private Thread thread = null;
private SimpleDateFormat sdf = new SimpleDateFormat("mm:ss:S");
private String[] split;
private SimpleStringProperty min, sec, millis, sspTime;
private long time;

public static void main(String[] args) {
    KTimer t = new KTimer();
    t.startTimer(00);
}

public KTimer() {
    min = new SimpleStringProperty("00");
    sec = new SimpleStringProperty("00");
    millis = new SimpleStringProperty("00");
    sspTime = new SimpleStringProperty("00:00:00");
}

public void startTimer(long time) {
    this.time = time;
    thread = new Thread(this);
    thread.setPriority(Thread.MIN_PRIORITY);
    thread.start();
}

public void stopTimer(long time) {
    if (thread != null) {
        thread.interrupt();
    }
    this.time = time;
    setTime(time);
}

public void setTime(long time) {
    this.time = time;
    split = sdf.format(new Date(time)).split(":");
    min.set(split[0]);
    sec.set(split[1]);

    if (split[2].length() == 1) {
        split[2] = "0" + split[2];
    }
    millis.set(split[2].substring(0, 2));

    sspTime.set(min.get() + ":" + sec.get() + ":" + millis.get());
}

public long getTime() {
    return time;
}

public SimpleStringProperty getSspTime() {
    return sspTime;
}

@Override
public void run() {
    try {
        while (!thread.isInterrupted()) {
            setTime(time);
            sleep(10);
            time = time + 10;
        }
    } catch (Exception e) {
    }

}
}//end of class

Now just get a listener on the property for your GUI

Add vars

    KTimer ktimer;
    Label timeLabel;

in your class initialize the vars

    //Clock
    ktimer = new KTimer();
    timeLabel = new Label(ktimer.getSspTime().get());
    ktimer.getSspTime().addListener(new InvalidationListener() {

        @Override
        public void invalidated(Observable observable) {
            timeLabel.setText(ktimer.getSspTime().get());
        }
    });

then call the method to start and stop wherever you need to

Stop and reset is

                ktimer.stopTimer(0);

Start and Pause timer is

               ktimer.startTimer(ktimer.getTime());

Any improvements appreciated as the class is a bit CPU hungry..., but you can adjust the run thread and setTime(time) functions to suit the application

like image 444
KEV Avatar asked Feb 20 '12 01:02

KEV


People also ask

How to stop animationtimers in JavaFX?

After starting the animation timer, the method handle () of timer will be called in every frame. It can be stopped using stop (). Explanation: This is the method that stops the AnimationTimers. It can be restarted using start (). How to use animation timer in JavaFX?

What is the star in a JavaFX timer?

Instead, it stars from whatever the JavaFX animation pulse time is on the next pulse. In short, it’s a fairly arbitrary fifteen-digit timestamp. We can extend the animation timer to include a start time, and subtract that from every timestamp.

How do you pause an animation timer in Java?

Pausing an animation timer can be achieved by extending the AnimationTimer class to record the timestamps or length of a pause event. On restarting the animation, the total pause length is subtracted from each timestamp to give the appearance of a continuous animation.

How to add a timer to Java code?

In Java, a need may arise for certain scheduled tasks to be performed later or with a delay. We shall perform this by adding a timer to Java code. To add a timer to the code, we shall use the Timer class and the TimerTask class from the java.util package.


2 Answers

Here's a slightly different version (maybe better) and I'm not sure the synchronized methods are really necessary

package aaa;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import javafx.beans.property.SimpleStringProperty;

/**
 *
 * @author D07114915
 */
public class KTimer {

private SimpleDateFormat sdf = new SimpleDateFormat("mm:ss:S");
private String[] split;
private SimpleStringProperty sspTime;
private long time;
private Timer t = new Timer("Metronome", true);
private TimerTask tt;
boolean timing = false;

public KTimer() {
    sspTime = new SimpleStringProperty("00:00:00");
}

public void startTimer(final long time) {
    this.time = time;
    timing = true;
    tt = new TimerTask() {

        @Override
        public void run() {
            if (!timing) {
                try {
                    tt.cancel();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                updateTime();
            }
        }
    };
    t.scheduleAtFixedRate(tt, 10, 10);
}

public synchronized void stopTimer() {
    timing = false;
}

public synchronized void updateTime() {
    this.time = this.time + 10;
    split = sdf.format(new Date(this.time)).split(":");
    sspTime.set(split[0] + ":" + split[1] + ":" + (split[2].length() == 1 ? "0" + split[2] : split[2].substring(0, 2)));
}

public synchronized void moveToTime(long time) {
    stopTimer();
    this.time = time;
    split = sdf.format(new Date(time)).split(":");
    sspTime.set(split[0] + ":" + split[1] + ":" + (split[2].length() == 1 ? "0" + split[2] : split[2].substring(0, 2)));
}

public synchronized long getTime() {
    return time;
}

public synchronized SimpleStringProperty getSspTime() {
    return sspTime;
}
}
like image 154
KEV Avatar answered Sep 18 '22 22:09

KEV


Building on KEV's answer and various demos I found across the internet, here's a simple "count up" timer with 100ms precision:

package fxtimer;

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;

public class FXTimer extends Application {

    private Timeline timeline;
    private Label timerLabel = new Label(), splitTimerLabel = new Label();
    private DoubleProperty timeSeconds = new SimpleDoubleProperty(),
            splitTimeSeconds = new SimpleDoubleProperty();
    private Duration time = Duration.ZERO, splitTime = Duration.ZERO;

    @Override
    public void start(Stage primaryStage) {
        // Configure the Label
        // Bind the timerLabel text property to the timeSeconds property
        timerLabel.textProperty().bind(timeSeconds.asString());
        timerLabel.setTextFill(Color.RED);
        timerLabel.setStyle("-fx-font-size: 4em;");
        splitTimerLabel.textProperty().bind(splitTimeSeconds.asString());
        splitTimerLabel.setTextFill(Color.BLUE);
        splitTimerLabel.setStyle("-fx-font-size: 4em;");

        // Create and configure the Button
        Button button = new Button();
        button.setText("Start / Split");
        button.setOnAction(new EventHandler() {
            @Override
            public void handle(Event event) {
                if (timeline != null) {
                    splitTime = Duration.ZERO;
                    splitTimeSeconds.set(splitTime.toSeconds());
                } else {
                    timeline = new Timeline(
                        new KeyFrame(Duration.millis(100),
                        new EventHandler<ActionEvent>() {
                            @Override
                            public void handle(ActionEvent t) {
                                Duration duration = ((KeyFrame)t.getSource()).getTime();
                                time = time.add(duration);
                                splitTime = splitTime.add(duration);
                                timeSeconds.set(time.toSeconds());
                                splitTimeSeconds.set(splitTime.toSeconds());
                            }
                        })
                    );
                    timeline.setCycleCount(Timeline.INDEFINITE);
                    timeline.play();
                }
            }
        });

        // Setup the Stage and the Scene (the scene graph)
        StackPane root = new StackPane();
        Scene scene = new Scene(root, 300, 250);

        // Create and configure VBox
        // gap between components is 20
        VBox vb = new VBox(20);
        // center the components within VBox
        vb.setAlignment(Pos.CENTER);
        // Make it as wide as the application frame (scene)
        vb.setPrefWidth(scene.getWidth());
        // Move the VBox down a bit
        vb.setLayoutY(30);
        // Add the button and timerLabel to the VBox
        vb.getChildren().addAll(button, timerLabel, splitTimerLabel);
        // Add the VBox to the root component
        root.getChildren().add(vb);

        primaryStage.setTitle("FX Timer");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }
}
like image 21
Daniel Avatar answered Sep 21 '22 22:09

Daniel