JavaFX 秒表计时器

发布于 2025-01-07 07:51:05 字数 2467 浏览 1 评论 0原文

这是一个用于 JavaFX 的简单秒表的类,根据需要设置 Label 对象的样式

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

现在只需在 GUI 的属性上获取一个侦听器,

在类中添加变量,

    KTimer ktimer;
    Label timeLabel;

初始化变量,

    //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());
        }
    });

然后在需要

停止和 停止的地方调用方法来启动和停止重置是

                ktimer.stopTimer(0);

启动计时器,暂停计时器是

               ktimer.startTimer(ktimer.getTime());

任何改进,因为该类有点占用 CPU...,但您可以调整运行线程和 setTime(time) 函数以适应应用程序

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

新雨望断虹 2025-01-14 07:51:05

这是一个稍微不同的版本(也许更好),我不确定同步方法是否真的有必要

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;
}
}

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;
}
}
剑心龙吟 2025-01-14 07:51:05

基于 KEV 的答案和我在互联网上找到的各种演示,这里有一个简单的“向上计数”计时器,精度为 100 毫秒:

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);
    }
}

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);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文