【问题标题】:JavaFX GraphicsContext clearRect doesn't work with clip maskJavaFX GraphicsContext clearRect 不适用于剪辑蒙版
【发布时间】:2016-02-14 03:42:16
【问题描述】:

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 已部分解决了该问题。上面的代码现在可以正常工作了。但是,使用非矩形剪辑蒙版仍然存在同样的问题。例如

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

我意识到我可以使用 save 和 restore 来取回一个矩形剪辑蒙版,然后 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);
    }
}

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

【问题讨论】:

    标签: java javafx javafx-8


    【解决方案1】:

    根据编辑 2,这种行为似乎是一个错误。总之,在设置非矩形剪辑时,clearRect 不起作用。 (如果即使使用矩形剪辑也无法正常工作,请更新到最新的 JDK。)我已经为此提交了错误报告。

    【讨论】:

      【解决方案2】:

      虽然我同意这个问题应该得到解决,但我正面临着事实并非如此,但我已经提出了一个至少可以满足我特定需求的解决方案。

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

      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);
                      }
                  }
              }
          }
      

      【讨论】:

        【解决方案3】:

        代码在带有 JavaFX 8u40 的 Windows 7 上运行良好。

        您应该做的是提供MCVE。没有人能猜到你还用 GraphicsContext 做了什么。可能缺少saverestore 等等。顺便说一句,您的代码缺少closePath()


        编辑前回答:

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

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

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

        我建议您将矩形移到中心,并使用填充方法使其对您更明显。

        您的代码没有 clearRect:

        您的带有 clearRect 的代码:

        【讨论】:

        • 虽然我相信这对你有用,但这绝对不适合我。抱歉不清楚,但是当我说 clearRect 没有做任何事情时,我的意思是它甚至没有擦除(四分之一)椭圆(我只有笔划来说明剪辑蒙版的位置)l。像你建议的那样填充背景然后做 clearRect 仍然没有影响,它看起来像你的第一张图片。
        • 您在哪个系统上使用哪个 JavaFX 版本?因为使用您使用的完全相同的代码删除了椭圆形。顺便说一句,closePath() 丢失了。下次您有问题时应该提供MCVE。重点是完成
        • 我已将我的 JDK 安装更新到最新版本,该问题现已部分修复。原始代码现在按预期工作。但是,如果您设置非矩形剪辑蒙版(使用弧),则 clearRect 仍然无法正常工作。请参阅我的编辑。我已经添加了您推荐的完整代码示例,您能重现我的问题吗?非常感谢您的帮助:)
        • 看起来你运气不好,只能使用背景颜色进行填充。 clearRect 需要矩形剪辑而不是非矩形路径才能产生任何效果。如果您使用它,它甚至都不起作用。 G。使用 moveTo/lineTo 创建一个简单的三角形并对其进行剪辑。您可以提交错误报告。
        • 感谢您的帮助。我已经向您授予了赏金并提交了错误报告。
        猜你喜欢
        • 1970-01-01
        • 2015-05-04
        • 2012-12-11
        • 2014-11-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-17
        • 2016-11-01
        相关资源
        最近更新 更多