使用Snapshot JavaFx移动画布的一部分

时间:2019-03-20 16:09:44

标签: java canvas javafx javafx-8

我正在编写一个功能,该功能可以将画布的选定部分移到另一点,这是项目的一部分,该项目包括开发诸如paint之类的程序。

这是应该允许移动的功能的类

public class TraslationTool {

private Canvas canvas;
private GraphicsContext gc;
private List<Canvas> list;
private double x1;
private double y1;
private double x2;
private double y2;

public TraslationTool(List<Canvas> list, double x1, double y1, double x2, double y2) {
    canvas = list.get(list.size() - 1);
    gc = canvas.getGraphicsContext2D();
    this.x1 = x1;
    this.y1 = y1;
    this.x2 = x2;
    this.y2 = y2;
    this.list = list;
}

public void traslate(double posX, double posY) {
    if (posX > 0 && posY > 0 && checkSelection()) {

        int width = (int) x2 - (int) x1;
        int height = (int) y2 - (int) y1;
        Rectangle2D bound = new Rectangle2D(x1, y1, width, height);

        SnapshotParameters params = new SnapshotParameters();
        params.setViewport(bound);
        params.setFill(Color.TRANSPARENT);
        WritableImage write = new WritableImage(width, height);
        Image image = canvas.snapshot(params, write);

        gc.clearRect(x1, y1, width, height);
        gc.drawImage(image, posX, posY);
    }
}

private boolean checkSelection() {
    if(this.x1 == 0 || this.y1 == 0 || this.x2 == 0 || this.y2 == 0) {
        return false;
    }
    if (this.x1 > this.x2) {
        double tempX = this.x1;
        this.x1 = this.x2;
        this.x2 = tempX;
    }
    if (this.y1 > this.y2) {
        double tempY = this.y1;
        this.y1 = this.y2;
        this.y2 = tempY;
    }
    return true;
} }

这是控制器处理画布的部分

drawingCanvas.setOnMousePressed(event -> {
        Canvas c = new Canvas(drawingCanvasWidth, drawingCanvasHeight);
        c.setOnMousePressed(drawingCanvas.getOnMousePressed());
        c.setOnMouseDragged(drawingCanvas.getOnMouseDragged());
        c.setOnMouseReleased(drawingCanvas.getOnMouseReleased());
        c.setOnMouseMoved(drawingCanvas.getOnMouseMoved());
        c.setOnMouseExited(drawingCanvas.getOnMouseExited());

        try {
            if (list.contains(list.get(++counter))) {
                for (int i = list.size() - 1; i >= counter; i--) {
                    list.remove(i);
                }
            }
        } catch (IndexOutOfBoundsException e) {

        }

        list.add(c);
        anchorPane.getChildren().add(c);
        gc = c.getGraphicsContext2D();
        gc.setLineWidth(size);

        x1 = event.getX();
        y1 = event.getY();

        if (event.getButton() == MouseButton.PRIMARY) {
            gc.setStroke(primaryColor);
            shapeDrawer.setCanvas(c, primaryColor);
        } else if (event.getButton() == MouseButton.SECONDARY) {
            gc.setStroke(secondaryColor);
            shapeDrawer.setCanvas(c, secondaryColor);
        }

        Color wantedColor = (Color) gc.getStroke();

        if (toolIsPressed) {
            if (toolPressed == hboxRubber) {
                gc.setStroke(Color.WHITE);
            } else if (toolPressed == hboxPencil) {
                gc.setLineWidth(0.25 * size);
            } else if (toolPressed == hboxDropper) {
                DropperTool dropperTool = new DropperTool(list, (int) event.getX(), (int) event.getY());
                Color tempColor = dropperTool.getColor();
                shapeDrawer.setCanvas(c, tempColor);
                if (event.getButton() == MouseButton.PRIMARY) {
                    shapeDrawer.setCanvas(c, primaryColor);
                    primaryColor = tempColor;
                    defColor1.setStyle("-fx-border-color: gray; -fx-background-color: " + hexToRgb(tempColor));
                } else if (event.getButton() == MouseButton.SECONDARY) {
                    shapeDrawer.setCanvas(c, secondaryColor);
                    secondaryColor = tempColor;
                    defColor2.setStyle("-fx-border-color: gray; -fx-background-color: " + hexToRgb(tempColor));
                }
                gc.setStroke(tempColor);
            } else if (toolPressed == hboxPolygon) {
                if (!polygonIsFirst) {
                    x1 = x2;
                    y1 = y2;
                } else {
                    polyX = x1;
                    polyY = y1;
                }
            } else if (toolPressed == hboxBucket) {
                BucketTool bucketTool = new BucketTool(list, (int) event.getX(), (int) event.getY(), wantedColor);
                bucketTool.paint();
            }
        }

        gc.beginPath();
        gc.moveTo(x1, y1);
        changesMade = true;
    });

    //Logic for show/unshow the Drawing Grid 
    hboxGrid.setOnMousePressed(event -> {
        if (gridIsPressed) {
            gridIsPressed = false;
            grid.setGridLinesVisible(gridIsPressed);
        } else {
            gridIsPressed = true;
            grid.setGridLinesVisible(gridIsPressed);
        }
    });


    /*
     Handle shapes.
     */
    drawingCanvas.setOnMouseReleased(event -> {
        x2 = event.getX();
        y2 = event.getY();

        if (x1 == x2 && y1 == y2 && toolIsPressed) {
            return;
        }

        changesMade = true;

        double width = x2 - x1;
        double height = y2 - y1;

        if (toolPressed == hboxLine) {
            shapeDrawer.drawLine(x2, y2);
        } else if (toolPressed == hboxRectangle) {
            shapeDrawer.drawRectangle(x1, y1, width, height);
        } else if (toolPressed == hboxOval) {
            shapeDrawer.drawOval(x1, y1, width, height);
        } else if (toolPressed == hboxCircle) {
            shapeDrawer.drawCircle(x1, y1, width, height);
        } else if (toolPressed == hboxSquare) {
            shapeDrawer.drawSquare(x1, y1, width, height);
        } else if (toolPressed == hboxTriangle) {
            shapeDrawer.drawTriangle(x1, y1, x2, y2, width);
        } else if (toolPressed == hboxRoundRectangle) {
            shapeDrawer.drawRoundRectangle(x1, y1, width, height);
        } else if (toolPressed == hboxPolygon) {
            if (polygonIsFirst) {
                polygonIsFirst = false;
            }
            if (x2 >= polyX - 10 && x2 <= polyX + 10 && y2 <= polyY + 10 && y2 >= polyY - 10) {
                gc.lineTo(polyX, polyY);
                gc.stroke();
                polygonIsFirst = true;
                return;
            }
            gc.lineTo(x2, y2);
            gc.stroke();
        } else if (toolPressed == hboxMove) {
            TraslationTool move = new TraslationTool(list, x1, y1, x2, y2);
            move.traslate(50, 50);
        }
    });
}

我使用的是画布的分层系统,以启用撤消/重做功能。 为了允许移动功能,我对Canvas的所需部分进行了快照,然后将此快照写入所需的坐标中。问题在于,当我执行代码时,在TraslationTool类上的调用仅创建一个新的Canvas层,而不执行移动功能。 我的想法是在创建新层时出现了问题,但是我不能理解它是什么。抱歉,很长的帖子,请提前解决。

1 个答案:

答案 0 :(得分:0)

我已经通过改变方法解决了我的问题。画布移动部分的问题归因于撤消/重做功能的实现(画布的分层系统在渲染WritableImage时产生了问题)。我已经使用This Solution更改了撤消/重做功能的实现,通过这种方式,Class TraslationTool可以工作。

这是我用于翻译画布一部分的代码:

public class MovingTool implements DrawOperation {

private final Canvas canvas;
private double x1;
private double y1;
private double x2;
private double y2;
private final double posX;
private final double posY;

public MovingTool(Canvas canvas, double x1, double y1, double x2, double y2, double posX, double posY) {
    this.canvas = canvas;
    this.x1 = x1;
    this.y1 = y1;
    this.x2 = x2;
    this.y2 = y2;
    this.posX = posX;
    this.posY = posY;
}

@Override
public void draw(GraphicsContext gc) {
    if ((posX >= 0) && (posY >= 0)) {

        checkSelection();

        int width = (int) x2 - (int) x1;
        int height = (int) y2 - (int) y1;
        Rectangle2D bound = new Rectangle2D(x1, y1, width, height);

        SnapshotParameters params = new SnapshotParameters();
        params.setViewport(bound);
        params.setFill(Color.TRANSPARENT);
        WritableImage write = new WritableImage(width, height);
        Image image = canvas.snapshot(params, write);

        gc.clearRect(x1, y1, width, height);
        gc.drawImage(image, x1, y1);
    }
}

private void checkSelection() {
    if (this.x1 > this.x2) {
        double tempX = this.x1;
        this.x1 = this.x2;
        this.x2 = tempX;
    }
    if (this.y1 > this.y2) {
        double tempY = this.y1;
        this.y1 = this.y2;
        this.y2 = tempY;
    }
}}