在JavaFX画布上应用DropShadow作为单独的层

在JavaFX画布上应用DropShadow作为单独的层,java,canvas,javafx,paint,layer,Java,Canvas,Javafx,Paint,Layer,我正在制作一个绘画程序,但是在用户绘制的图形周围有一个DropShadow。当它们擦除时,它也会擦除DropShadow。如果我尝试重新应用DropShadow(使其环绕图形的新边界),它会起作用,但它会使已应用的DropShadow的其余部分变暗,这是我不希望看到的 我能想到的解决方案有两方面: 删除DropShadow效果,并在每次擦除时重新应用它。据我所知,在使用GraphicsContext.applyEffect()时,这是不可能的 在单独的画布上应用DropShadow,每次擦除时将

我正在制作一个绘画程序,但是在用户绘制的图形周围有一个
DropShadow
。当它们擦除时,它也会擦除
DropShadow
。如果我尝试重新应用
DropShadow
(使其环绕图形的新边界),它会起作用,但它会使已应用的
DropShadow
的其余部分变暗,这是我不希望看到的

我能想到的解决方案有两方面:

  • 删除
    DropShadow
    效果,并在每次擦除时重新应用它。据我所知,在使用
    GraphicsContext.applyEffect()时,这是不可能的
  • 在单独的画布上应用
    DropShadow
    ,每次擦除时将其清除并重新绘制。下面的代码实现了我在这个解决方案中令人尴尬的尝试
  • 以下是当前发生的情况的图片:

    这是我的密码

    FXMLDocument.fxml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.canvas.Canvas?>
    <?import javafx.scene.layout.AnchorPane?>
    <?import javafx.scene.layout.Pane?>
    
    <AnchorPane id="AnchorPane" prefHeight="399.0" prefWidth="465.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="cartographerfx.FXMLDocumentController">
        <children>
          <Pane fx:id="canvasPane" layoutX="26.0" layoutY="20.0" prefHeight="362.0" prefWidth="417.0" style="-fx-border-style: solid;">
             <children>
                <Canvas fx:id="canvas" height="362.0" onMouseDragged="#CanvasMouseDragged" onMousePressed="#CanvasMouseDown" onMouseReleased="#CanvasMouseUp" width="417.0" />
             </children>
          </Pane>
        </children>
    </AnchorPane>
    
    matcherfx.java

    package cartographerfx;
    
    import java.net.URL;
    import java.util.ResourceBundle;
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.canvas.Canvas;
    import javafx.scene.canvas.GraphicsContext;
    import javafx.scene.effect.DropShadow;
    import javafx.scene.input.MouseButton;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.layout.Pane;
    import javafx.scene.paint.Color;
    
    /**
     *
     * @author Dan
     */
    public class FXMLDocumentController implements Initializable {
    
        @FXML
        Canvas canvas;
        Canvas shadowLayer;
    
        @FXML
        Pane canvasPane;
    
        private GraphicsContext gc;
        private GraphicsContext sgc;
        private boolean isDragging;
        private double lastX;
        private double lastY;
    
        @FXML
        public void CanvasMouseDragged(MouseEvent event) {
    
            if (isDragging) {
                if (event.getButton() == MouseButton.PRIMARY) {
    
                    gc.setStroke(Color.BLUE);
    
                    gc.setLineWidth(10);
                    gc.strokeLine(lastX, lastY, event.getX(), event.getY());
                } else if (event.getButton() == MouseButton.SECONDARY) {
                    gc.clearRect(event.getX(), event.getY(), 10, 10);
                }
    
                lastX = event.getX();
                lastY = event.getY();
            }
    
    
        }
    
        @FXML
        public void CanvasMouseDown(MouseEvent event) {
            isDragging = true;
    
            lastX = event.getX();
            lastY = event.getY();
    
            if (event.getButton() == MouseButton.MIDDLE)
            {
                sgc = gc;
                sgc.applyEffect(new DropShadow());
    
            }
        }
    
        @FXML
        public void CanvasMouseUp(MouseEvent event) {
            isDragging = false;
        }
    
        @Override
        public void initialize(URL url, ResourceBundle rb) {
    
            gc = canvas.getGraphicsContext2D();
            isDragging = false;
    
            shadowLayer = new Canvas(canvas.getWidth(), canvas.getHeight());
    
            sgc = shadowLayer.getGraphicsContext2D();
            canvasPane.getChildren().add(shadowLayer);
            shadowLayer.toBack();
        }
    
    }
    
    package cartographerfx;
    
    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    
    /**
     *
     * @author Dan
     */
    public class CartographerFX extends Application {
    
        @Override
        public void start(Stage stage) throws Exception {
            Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
    
            Scene scene = new Scene(root);
    
            stage.setScene(scene);
            stage.show();
        }
    
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
            launch(args);
        }
    
    }
    

    我不明白为什么每个人似乎都在使用画布,而场景图更适合这个任务。为什么不使用普通的窗格和路径呢。然后,可以将阴影效果直接应用于路径。场景图的优点是,您可以根据需要频繁地单独编辑每个元素,而画布基本上只是一个概念上的图像,绘制后您根本无法编辑它。

    Lol当您使用谷歌“使用javafx绘制”时,每个结果都使用画布,但我看了看,使用场景图似乎可以做得很好。你知道我如何放入一个行为类似于clearRect()的橡皮擦吗?看一下本教程:对于橡皮擦,可以使用形状减法。