BANDREVU AKHIL KUMAR
BANDREVU AKHIL KUMAR

Reputation: 107

how to draw a straight line in javafx that updates itself when the user moves the mouse?

So, I know how to do free hand lines but I want a straight line so when a user clicks a point to the point where the user releases the mouse and when the user drags the mouse the end point should move with the mouse i.e similar to drawing straight lines in the paint app.

Presently working with this code:

public class JavaFX_DrawOnCanvas extends Application {

    @Override
    public void start(Stage primaryStage) {

        Canvas canvas = new Canvas(400, 400);
        final GraphicsContext graphicsContext = canvas.getGraphicsContext2D();
        initDraw(graphicsContext);

        canvas.addEventHandler(MouseEvent.MOUSE_PRESSED, 
                new EventHandler<MouseEvent>(){

            @Override
            public void handle(MouseEvent event) {
                graphicsContext.beginPath();
                graphicsContext.moveTo(event.getX(), event.getY());
                graphicsContext.stroke();
            }
        });

        canvas.addEventHandler(MouseEvent.MOUSE_DRAGGED, 
                new EventHandler<MouseEvent>(){

            @Override
            public void handle(MouseEvent event) {
                graphicsContext.lineTo(event.getX(), event.getY());
                graphicsContext.stroke();
            }
        });

        canvas.addEventHandler(MouseEvent.MOUSE_RELEASED, 
                new EventHandler<MouseEvent>(){

            @Override
            public void handle(MouseEvent event) {

            }
        });

        StackPane root = new StackPane();
        root.getChildren().add(canvas);
        Scene scene = new Scene(root, 400, 400);
        primaryStage.setTitle("java-buddy.blogspot.com");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

    private void initDraw(GraphicsContext gc){
        double canvasWidth = gc.getCanvas().getWidth();
        double canvasHeight = gc.getCanvas().getHeight();

        gc.setFill(Color.LIGHTGRAY);
        gc.setStroke(Color.BLACK);
        gc.setLineWidth(5);

        gc.fill();
        gc.strokeRect(
                0,              //x of the upper left corner
                0,              //y of the upper left corner
                canvasWidth,    //width of the rectangle
                canvasHeight);  //height of the rectangle

        gc.setFill(Color.RED);
        gc.setStroke(Color.BLUE);
        gc.setLineWidth(1);

    }

}

How to modify the mouse drag event to draw straight lines and not free hand?

Upvotes: 2

Views: 5141

Answers (1)

Enigo
Enigo

Reputation: 3885

Generally, I agree with comments - it is easier to do this using Line. But with canvas you can achieve the same like so:

public class JavaFX_DrawOnCanvas extends Application {

    private Pair<Double, Double> initialTouch;
    private Canvas layer = new Canvas();

    @Override
    public void start(Stage primaryStage) {
        StackPane root = new StackPane();

        Canvas canvas = new Canvas(400, 400);
        final GraphicsContext graphicsContext = canvas.getGraphicsContext2D();
        initDraw(graphicsContext);
        canvas.addEventHandler(MouseEvent.MOUSE_PRESSED,
                new EventHandler<MouseEvent>(){

                    @Override
                    public void handle(MouseEvent event) {
                        Canvas newLayer = new Canvas(400, 400);
                        GraphicsContext context = newLayer.getGraphicsContext2D();
                        initDraw(context);

                        layer = newLayer;
                        root.getChildren().add(0, newLayer);
                        initialTouch = new Pair<>(event.getSceneX(), event.getSceneY());
                    }
                });

        canvas.addEventHandler(MouseEvent.MOUSE_DRAGGED,
                new EventHandler<MouseEvent>(){

                    @Override
                    public void handle(MouseEvent event) {
                        GraphicsContext context = layer.getGraphicsContext2D();
                        context.clearRect(0, 0, layer.getWidth(), layer.getHeight());
                        context.strokeLine(initialTouch.getKey(), initialTouch.getValue(), event.getSceneX(), event.getSceneY());
                    }
                });

        root.getChildren().add(canvas);
        Scene scene = new Scene(root, 400, 400);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void initDraw(GraphicsContext gc){
        double canvasWidth = gc.getCanvas().getWidth();
        double canvasHeight = gc.getCanvas().getHeight();

        gc.setFill(Color.LIGHTGRAY);
        gc.setStroke(Color.BLACK);
        gc.setLineWidth(5);

        gc.fill();
        gc.strokeRect(
                0,              //x of the upper left corner
                0,              //y of the upper left corner
                canvasWidth,    //width of the rectangle
                canvasHeight);  //height of the rectangle

        gc.setFill(Color.RED);
        gc.setStroke(Color.BLUE);
        gc.setLineWidth(1);

    }

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

}

So, basically you need to create separate layer for each new line and use strokeLine method. Note, that newly added layer must be added at the 0 index to the root children because otherwise event handler of the main canvas would stop process events.

Upvotes: 4

Related Questions