JavaFX GraphicsContext clearRect不适用于剪辑蒙版

时间:2015-11-12 17:41:28

标签: java javafx javafx-8

GraphicsContext的clearRect方法的文档声明它使用当前剪辑,但这对我来说当前不起作用。考虑:

GraphicsContext context = canvas.getGraphicsContext2D();
context.beginPath();
context.rect(0,0,100,100); //Set the current path to a rectangle
context.stroke(); //Highlights where the current path is
context.clip();   //Intersect current clip with rectangle
context.fillOval(80, 80, 40, 40); //This correctly draws the oval clipped
context.clearRect(0,0,100,100); //This does nothing at all

上面的代码正确设置了剪辑蒙版,正如fillOval正常工作所证明的那样,但是clearRect什么都不做(尽管它没有context.clip()就能正常工作)。为什么是这样?

(请注意,我特别需要剪辑蒙版工作,因为稍后我计划将其设置为特定形状以擦除非矩形形状。)

- 编辑 -

要清楚,clearRect确实没什么,甚至没有删除椭圆形。我意识到它不会擦除抚摸的矩形,但这不是我所关心的。

- 编辑2 -

更新到最新的JDK已经部分修复了该问题。上面的代码现在可以正常工作。但是,使用非矩形剪辑蒙版仍然存在同样的问题。 e.g。

GraphicsContext context = canvas.getGraphicsContext2D();
context.beginPath();
context.arc(50, 50, 40, 40, 0, 360); // Make a circular clip mask
context.closePath();
context.clip();
context.fillRect(0, 0, 200, 200); //Draw a circle clipped correctly, shows clip mask is working
context.clearRect(0, 0, 200, 200); //Does nothing

我意识到我可以使用保存和恢复来获取矩形剪辑蒙版,然后clearRect将起作用。但是我希望能够以非矩形形状擦除。

用于复制它的完整代码(通过在eclipse中创建一个新的JavaFX项目并添加以上行来创建):

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            BorderPane root = new BorderPane();
            Scene scene = new Scene(root, 400, 400);
            primaryStage.setScene(scene);
            primaryStage.show();

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

            GraphicsContext context = canvas.getGraphicsContext2D();
            context.beginPath();
            context.arc(50, 50, 40, 40, 0, 360);
            context.closePath();
            context.clip();
            context.fillRect(0, 0, 200, 200);
            context.clearRect(0, 0, 200, 200);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

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

这应显示一个空白屏幕,但圆圈未被清除。

3 个答案:

答案 0 :(得分:1)

虽然我同意应该解决此问题,但面对事实并非如此,但我提出了至少可以满足我的特定需求的解决方案。

这是一种使用GraphicsContext基于SVGPath清除区域的方法。

private void clearPath(GraphicsContext gc, SVGPath path) {
        int xstart = (int) path.getLayoutX();
        int xend = (int) (xstart + path.getLayoutBounds().getMaxX());
        int ystart = (int) path.getLayoutY();
        int yend = (int) (ystart + path.getLayoutBounds().getMaxY());

        PixelWriter pw = gc.getPixelWriter();
        for (int x = xstart; x <= xend; x++) {
            for (int y = ystart; y <= yend; y++) {
                if(path.contains(new Point2D(x, y))) {
                    pw.setColor(x, y, Color.TRANSPARENT);
                }
            }
        }
    }

答案 1 :(得分:0)

使用JavaFX 8u40,Windows 7上的代码工作得很好。

您应该做的是提供MCVE。没人能猜到你用GraphicsContext做了什么。可能会遗漏saverestore,而不会丢失。顺便说一句,您的代码缺少closePath()

在编辑前回答:

您面临的问题是JavaFX绘制线条的方式。查看Node类的文档:

  

在设备像素级别,整数坐标映射到角落   像素和像素中心之间的裂缝出现在   整数像素位置之间的中点。因为所有的坐标   值用浮点数指定,坐标可以   精确指向这些角(当浮点值有   精确整数值)或像素上的任何位置。例如,a   坐标(0.5,0.5)将指向左上角的中心   舞台上的像素。类似地,在(0,0)处具有尺寸的矩形   10乘10将跨越左上角的左上角   舞台上的像素位于第10个像素的右下角   第10条扫描线。那个里面最后一个像素的像素中心   矩形位于坐标处(9.5,9.5)。

这就是为什么你在右边和底部有一条细线的原因。这些行不是crisp

我建议您将矩形移动到中心,并使用填充方法让您更加清晰可见。

没有clearRect的代码:

enter image description here

您使用clearRect的代码:

enter image description here

答案 2 :(得分:0)

根据编辑2,这种行为似乎是一个错误。总之,当设置非矩形剪辑时,clearRect无效。 (如果使用矩形剪辑它不适合你,请更新到最新的JDK。)我已经为此提交了一个错误报告。