Updated my question to meet the minimal reproducible example. I'm creating a simple drawing app, where user can do free drawings.
I want the user to be able to undo the last drawing on canvas. For that purpose I am saving the mouseclicked
and mousedragged
positions (x, y) in two ArrayLists
, then using the saved positions to clear it via graphics context's clearRect()
function. But clearRect()
is not clearing everything. I tried saving coordinates in a HashMap
and double[][]
but I am getting the same result. I'll try a different approach (layered canvas) for this issue, but I really want to understand this problem. I attached below the screenshots of what is drawn and what is cleared and is redrawn back with Redo
button. Related code:
import java.util.ArrayList;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class DrawOnCanvas extends Application {
Scene scene;
Pane canvasPane, buttonPane;
BorderPane mainPane;
Canvas canvas;
GraphicsContext gxc;
Button undoButton, redoButton;
private ArrayList<Double> xPos = new ArrayList<>();
private ArrayList<Double> yPos = new ArrayList<>();
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void start(Stage stage) throws Exception {
mainPane = new BorderPane();
canvasPane = new Pane();
buttonPane = new Pane();
canvas = new Canvas(500, 500);
canvasPane.setStyle("-fx-border-color: black");
gxc = canvas.getGraphicsContext2D();
gxc.setLineWidth(2);
undoButton = new Button("Undo");
redoButton = new Button("Redo");
redoButton.relocate(200, 0);
canvasPane.getChildren().add(canvas);
buttonPane.getChildren().addAll(undoButton, redoButton);
mainPane.setCenter(canvasPane);
mainPane.setBottom(buttonPane);
scene = new Scene(mainPane);
startDrawing(gxc, canvas);
undoDrawing(gxc, undoButton);
redoDrawing(gxc, redoButton);
stage = new Stage();
stage.setScene(scene);
stage.show();
}
public void startDrawing(GraphicsContext gc, Canvas can) {
can.setOnMousePressed(e -> {
gc.beginPath();
gc.moveTo(e.getX(), e.getY());
gc.stroke();
xPos.add(e.getX());
yPos.add(e.getY());
});
can.setOnMouseDragged(e -> {
gc.lineTo(e.getX(), e.getY());
gc.stroke();
gc.closePath();
gc.beginPath();
gc.moveTo(e.getX(), e.getY());
xPos.add(e.getX());
yPos.add(e.getY());
});
}
public void undoDrawing(GraphicsContext gCon, Button undo) {
undo.setOnMouseClicked(e -> {
for (int i = 0; i < xPos.size(); i++) {
System.out.println(xPos.get(i) + " " + yPos.get(i));
gCon.clearRect(xPos.get(i) - 2, yPos.get(i) - 2, 5, 5);
}
});
}
public void redoDrawing(GraphicsContext gCon, Button undo) {
undo.setOnMouseClicked(e -> {
for (int i = 0; i < xPos.size(); i++) {
gCon.fillRect(xPos.get(i) - 2, yPos.get(i) - 2, 5, 5);
System.out.println(xPos.get(i) + " " + yPos.get(i));
}
});
}
}