如何在JavaFX方法(如GraphicsContext.fillArc())中应用抗锯齿?

4

我是javafx的新手,正在使用它的渲染功能编写游戏,具体来说就是在eclipse中使用GraphicsContext.fillArc()等函数。

这是我的当前代码:

        BorderPane root = new BorderPane();

        Scene scene = new Scene(root, 400, 400);
        primaryStage.setScene(scene);
        scene.getStylesheets()
                .add(getClass().getResource("application.css").toExternalForm());

        Canvas canvas = new Canvas(400, 400);
        root.getChildren().add(canvas);

        GraphicsContext gc = canvas.getGraphicsContext2D();
        new AnimationTimer()
        {
            public void handle(long currentNanoTime)
            {
                gc.setFill(Color.BLUE);
                gc.fillArc(150, 150, 100, 100, 0, 240, ArcType.ROUND);
            }
        }.start();
        primaryStage.show();

然而,fillArc() 方法在我的屏幕上呈现的形状边缘不平滑。我希望应用抗锯齿处理以使边缘平滑。然而,在 GraphicsContext 类中找不到任何相关方法,将 scene 的实例化更改为 new Scene(root, 400, 400, false, SceneAntialiasing.BALANCED); 也没有效果。因此,我的问题是如何在 GraphicsContext.fillArc() 上实现抗锯齿处理,或者是否基本上可能?
另外,我对 javafx 和 cgi 一般都非常陌生,所以欢迎任何建议和推荐。
更新:
正如 @jewelsea 建议的那样,当代码块 gc.setFill(Color.BLUE); gc.fillArc(150, 150, 100, 100, 0, 240, ArcType.ROUND); 放置在 AnimationTimer 的匿名子类之外时,渲染的图像是抗锯齿的。目前我们都无法弄清楚原因。供参考。

2
有趣的是,如果你注释掉动画计时器,仅绘制弧形而不使用它,那么弧形会很好地反锯齿。我不知道为什么。 - jewelsea
@jewelsea 非常有趣。我会研究一下 AnimationTimer 类的属性。 - cyqsimon
1个回答

4
我在玩CanvasAnimationTimer时遇到了类似的问题。解决方案的一个重要关键是@jewelsea发布的评论

"...如果你注释掉动画计时器,只是绘制圆弧而没有它,那么圆弧会很好地实现抗锯齿..."

这基本上意味着,如果我们绘制圆弧一次,它就会进行抗锯齿处理。但如果我们在AnimationTimerhandle()方法中绘制它,则每秒会绘制60次。在handle()方法中添加长时间的休眠后,可以更清楚地看到结果。第一次在白色背景上渲染圆形,并且看起来是期望的。第二次在之前的蓝色圆形上渲染蓝色圆形。因为抗锯齿而部分着色成蓝色的像素变得更暗。当第三次绘制圆时,情况也是如此。以下图像显示了经过1、2、3、4、5、10和50次迭代后圆弧的放大部分:

arcs

问题的一个简单解决方案是在渲染任何内容之前用背景颜色填充画布:
public void handle(long currentNanoTime) {
    gc.setFill(Color.WHITE);
    gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());

    gc.setFill(Color.BLUE);
    gc.fillArc(150, 150, 100, 100, 0, 240, ArcType.ROUND);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接