JavaFX图形:如何更改绘图设置?

时间:2017-09-10 16:08:54

标签: java javafx

近一个月前,我正在测试JavaFX图形API,但我担心性能。性能问题是我必须传递一个Paint对象来着色形状。

问题:无法更改现有Paint

的设置

我只需要更新Paint,例如Color,但没有像Color#setRedColor#setGreenColor#setBlue和{{}这样的方法1}}。也没有字段(javafx.scene.paint.Color)。

性能

我可以尝试更改Color#setOpacity的设置的唯一方法是构建另一个Paint,但这将涉及运行垃圾收集器。这是对的吗?

编译器应根据它们的完全使用方式自动优化这些对象。但到目前为止,甲骨文在其编译器上没有说到这一点,至少对我而言。

如果他们说垃圾收集是好的,那么错误不是我的。我没有提到垃圾收集有用的任何内容。

重建Paint是一个很好的解决方案吗?你们也知道处理我想要的JavaFX替代品吗?

1 个答案:

答案 0 :(得分:1)

您所关心的问题并不存在。由于Paint是一个不可变类(出于多种原因这是一个很好的设计选择),更新JavaFX中某些颜色的正确方法是创建一个新的Paint实例并将其设置为需要的财产。以前使用过的实例不再引用它们将在未来的某个时间由垃圾收集器有效地清理。

这是一个简单的演示,每次渲染场景时都会创建新的Paint个实例(也是新的BackgroundBackgroundFill实例)。如果帧渲染超过25毫秒(任意阈值),它会打印警告。在我的系统上,它会警告前几帧,有时会在窗口隐藏并完全重新显示时发出警告。

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class UpdateColorContinuously extends Application {

    @Override
    public void start(Stage primaryStage) {
        Pane root = new Pane();
        root.setMinSize(600, 600);

        new AnimationTimer() {

            private long start = -1 ;
            private long lastUpdate ;

            @Override
            public void handle(long now) {
                if (start < 0) {
                    start = now ;
                    lastUpdate = now ;
                }
                long elapsed = now - start ;
                double elapsedSeconds  = elapsed / 1_000_000_000.0 ;
                Color newColor = Color.hsb(elapsedSeconds * 5, 1.0, 1.0);
                BackgroundFill fill = new BackgroundFill(newColor, CornerRadii.EMPTY, Insets.EMPTY);
                Background bg = new Background(fill);
                root.setBackground(bg);

                if (now - lastUpdate > 25_000_000) {
                    System.err.println("Warning: frame rendering took "+ (now-lastUpdate)/1_000_000 + " ms");
                }

                lastUpdate = now ;
            }

        }.start();

        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

我可能无法运行这么长时间以便GC需要运行;对Paint实例需要的内存量的保守估计是50个字节,因此您需要创建10^7这样的实例的顺序以使用500MB(现代中相当少量的RAM)桌面系统,可能相当于一次GC扫描)。因此,球场数据显示,这将在两天内产生一次GC扫描。