如何在 JavaFx 中创建计时器

在 JavaFx 中创建计时器是一项非常常见的任务。计时器在许多应用程序中都起到至关重要的作用,例如倒计时、计时比赛时间、更新界面等。本文将详细介绍在 JavaFx 中创建计时器的步骤,并提供一些示例和注意事项。

JavaFx 是一个用于构建富客户端应用程序的开发工具包,它提供了许多用于创建界面和实现交互的类和方法。要在 JavaFx 中创建计时器,我们可以使用 JavaFx 提供的 AnimationTimer 类或使用多线程技术。

一、使用 AnimationTimer 类创建计时器

AnimationTimer 是 JavaFx 提供的一个用于处理动画和一些循环任务的类。我们可以通过重写其 handle 方法来实现计时器的功能。以下是一个创建计时器的示例:

public class TimerExample extends Application {

    private final long ONE_SECOND = 1_000_000_000;
    private long startTime;

    @Override
    public void start(Stage primaryStage) {

        Label timerLabel = new Label("00:00:00");

        AnimationTimer timer = new AnimationTimer() {

            @Override
            public void start() {
                startTime = System.nanoTime();
                super.start();
            }

            @Override
            public void handle(long now) {
                long elapsedTime = now - startTime;
                long seconds = elapsedTime / ONE_SECOND;
                long minutes = (seconds / 60) % 60;
                long hours = (seconds / 3600) % 24;

                String timeString = String.format("%02d:%02d:%02d", hours, minutes, seconds % 60);
                timerLabel.setText(timeString);
            }
        };
        timer.start();

        // 添加其他界面组件并设置布局...

        primaryStage.setScene(new Scene(timerLabel, 200, 100));
        primaryStage.show();
    }

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

在上面的示例中,我们创建了一个 AnimationTimer 对象,并实现了 handle 方法。在每一帧中,我们都计算了当前时间与开始时间之间的差异,并将其转换为小时、分钟和秒钟显示在 label 中。通过使用 String.format 方法,我们可以将这些值格式化为 “HH:MM:SS” 的模式。最后,我们将更新后的时间字符串设置为 timerLabel 的文本。

二、使用多线程创建计时器

除了使用 AnimationTimer 类,我们还可以使用多线程技术来创建计时器。JavaFx 是基于事件驱动的框架,因此我们需要确保更新界面的操作在 JavaFx 的主线程中执行。以下是一个使用多线程创建计时器的示例:

public class TimerExample extends Application {

    private final long ONE_SECOND = 1_000;
    private long elapsedTime;

    @Override
    public void start(Stage primaryStage) {
        Label timerLabel = new Label("00:00:00");

        Thread timerThread = new Thread(() -> {
            while (true) {
                elapsedTime += ONE_SECOND;

                long seconds = elapsedTime / ONE_SECOND;
                long minutes = (seconds / 60) % 60;
                long hours = (seconds / 3600) % 24;

                String timeString = String.format("%02d:%02d:%02d", hours, minutes, seconds % 60);

                // 更新界面的操作必须在 JavaFx 主线程中执行
                Platform.runLater(() -> timerLabel.setText(timeString));

                try {
                    Thread.sleep(ONE_SECOND);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        timerThread.setDaemon(true);
        timerThread.start();

        // 添加其他界面组件并设置布局...

        primaryStage.setScene(new Scene(timerLabel, 200, 100));
        primaryStage.show();
    }

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

在上述示例中,我们创建了一个新的线程 timerThread,它在后台无限循环并更新 elapsedTime。在每一秒钟,线程会计算小时、分钟和秒钟,并使用 String.format 将其转换为 “HH:MM:SS” 格式的字符串。通过使用 Platform.runLater 方法,我们可以确保更新界面的操作在 JavaFx 的主线程中执行,从而避免多线程并发问题。

注意事项:

  1. 在 JavaFx 中创建计时器时,需要遵循更新界面的操作必须在 JavaFx 主线程中执行的规则。如果不遵循该规则,可能会引发线程安全问题。
  2. 在使用 AnimationTimer 类创建计时器时,handle 方法在每一帧被调用。因此,要计算逝去的时间,我们需要使用 System.nanoTime() 方法获取当前时间。
  3. 在使用多线程创建计时器时,我们可以使用 Thread.sleep 方法来控制计时器的精度。在每个时间片结束后,我们将线程睡眠 1 秒钟,并更新计时器的状态。要注意线程睡眠可能会引发 InterruptedException 异常,需要正确处理异常。
  4. 在终止应用程序时,要正确停止计时器线程。可以通过设置线程为守护线程 daemon 来实现线程自动停止。
  5. 为了优化性能,可以考虑增加计时器的精度。例如,使用毫秒而不是秒来进行计时,或者使用固定的时间间隔而不是睡眠期间的实际时间差作为逝去的时间。

总结:

本文详细介绍了在 JavaFx 中创建计时器的步骤,并提供了使用 AnimationTimer 类和多线程技术的示例。在应用程序开发过程中,计时器是一项常见而重要的功能,希望本文的内容能帮助读者了解如何在 JavaFx 中实现计时器,并注意一些细节和注意事项。