java - JavaFX 中任何类型的动画或时间线都会占用过多的 CPU

标签 java javafx javafx-8

我在配备 2.4 GHz Intel Core 2 Duo 处理器和 4GB RAM 的 MacBook Pro 上使用 JDK 8.0 附带的 JavaFx。

我有一个奇怪的行为,使用以下类:

import com.sun.javafx.perf.PerformanceTracker;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class HelloWorld extends Application {
    private static PerformanceTracker tracker;
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Hello World!");
        Button btn = new Button();
        btn.setText("Say 'Hello World'");
        btn.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                System.out.println("Hello World!");
            }
        });

        StackPane root = new StackPane();
        root.getChildren().add(btn);
        Scene scene= new Scene(root, 300, 250);
        primaryStage.setScene(scene);
        primaryStage.show();


        Label label1 = new Label();
        Label label2 = new Label();
        ((Pane)root).getChildren().addAll(label1, label2);

        scene.setOnKeyPressed((e)->{
            label2.setText(label1.getText());
        });



        tracker = PerformanceTracker.getSceneTracker(scene);
        AnimationTimer frameRateMeter = new AnimationTimer() {

            @Override
            public void handle(long now) {
                label1.setText(String.format("Current frame rate: %.3f fps", getFPS()));
            }
        };

        //frameRateMeter.start();


    }

    private float getFPS () {
        float fps = tracker.getAverageFPS();
        tracker.resetAverageFPS();
        return fps;
    }
}

执行此代码时,CPU 使用率在 0.2% 到最大 10% 之间。 如果我删除以下评论:

frameRateMeter.start();

我发现相同的代码使用 CPU 从 20% 到 40%。

这只是一个示例,但我编写的应用程序在注释掉上面的行后,运行时使用了大约 40% 的 CPU,删除注释后运行时则使用了接近 100% 的 CPU。

这正常吗?我注意到,添加连续执行的时间轴(也是非常简单的一个)的任何时间,都会产生 CPU 的荒谬使用。

在 JavaFX 中使用动画真的那么昂贵吗?还是我错过了一些东西?

任何帮助将不胜感激。

最佳答案

我认为您非常频繁地更新标签中的 FPS 值:

The class AnimationTimer allows to create a timer, that is called in each frame while it is active.

当您更新 label1 中的文本时,JavaFX 会一次又一次地绘制新框架。您可以轻松检查这一点:将 FPS 写入 STDOUT 而不是 label1:

...
System.out.println(String.format("Current frame rate: %.3f fps", tracker.getAverageFPS()));
// label1.setText(String.format("Current frame rate: %.3f fps", tracker.getAverageFPS()));
...

在这种情况下,您应该会看到较低的 FPS 速率。

因此,尝试使用任何 Java/JavaFX 计时器每隔一秒或半秒更新 FPS 值,即:

Timeline timeline = new Timeline(new KeyFrame(Duration.millis(500), event -> {
    label1.setText(String.format("Current frame rate: %.3f fps", tracker.getAverageFPS()));
}));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();

在我的 macOS 上,平均 CPU 值约为 1.8-2%。

关于java - JavaFX 中任何类型的动画或时间线都会占用过多的 CPU,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41422500/

相关文章:

javafx-2 - 如何在TextArea中显示多行文本

java - 如何使用属性制作自定义事件?

java - 如何通过 id 更改 fxml 标签文本

java - JavaFX 中的额外空间

java - 由于@OneToMany,JPA 更新记录失败

java - 在自定义 java 类中反序列化 MapWritable

java - 带数据验证的文本框

java - 评级栏返回默认值

java - Eclipse 项目中的文档存储在哪里?

Javafx tableview changelistener 经常变化