Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaFX - Clickable line on canvas

Tags:

java

javafx

I have this JavaFX application that lets you plot locations on a map and connect them.

enter image description here

I do this by drawing a map as a background image on a canvas and then drawing circles and lines on it. I have made the circles clickable by using the contains() method in the Circle class, but how can I make the lines clickable?

edit: Look at this example where I just draw a line and set an event handler:

    Canvas canvas = new Canvas();
    GraphicsContext gc = canvas.getGraphicsContext2D();

    gc.setLineWidth(5);
    gc.strokeLine(100, 100, 200, 200);

    canvas.setOnMouseClicked(event -> {
        double x = event.getX(), y = event.getY();
    });

My question is simply this: how do I finish the event handler so that it detects if the click is inside the line I just drew?

like image 878
Just some guy Avatar asked Jan 17 '15 12:01

Just some guy


People also ask

How do you make a new line in JavaFX?

String newLine = "\n"; Append or prepend the new line to your TextArea to create new lines.

What is a StackPane in JavaFX?

The StackPane layout pane places all the nodes into a single stack where every new node gets placed on the top of the previous node. It is represented by javafx.


1 Answers

You should create a canvas and add the nodes (Circle, Line, etc) to it. Then you add mouse listeners to the nodes.

Example:

import java.util.ArrayList;
import java.util.List;

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.stage.Stage;

public class DragNodes extends Application {

    public static List<Circle> circles = new ArrayList<Circle>();

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

    @Override
    public void start(Stage primaryStage) {

        Group root = new Group();

        Canvas canvas = new Canvas(300, 300);
        GraphicsContext gc = canvas.getGraphicsContext2D();
        drawShapes(gc);

        Circle circle1 = new Circle(50);
        circle1.setStroke(Color.GREEN);
        circle1.setFill(Color.GREEN.deriveColor(1, 1, 1, 0.7));
        circle1.relocate(100, 100);

        Circle circle2 = new Circle(50);
        circle2.setStroke(Color.BLUE);
        circle2.setFill(Color.BLUE.deriveColor(1, 1, 1, 0.7));
        circle2.relocate(200, 200);

        Line line = new Line(circle1.getLayoutX(), circle1.getLayoutY(), circle2.getLayoutX(), circle2.getLayoutY());
        line.setStrokeWidth(20);

        Pane overlay = new Pane();
        overlay.getChildren().addAll(circle1, circle2, line);

        MouseGestures mg = new MouseGestures();
        mg.makeDraggable(circle1);
        mg.makeDraggable(circle2);
        mg.makeDraggable(line);

        root.getChildren().addAll(canvas, overlay);

        primaryStage.setScene(new Scene(root, 800, 600));
        primaryStage.show();
    }

    private void drawShapes(GraphicsContext gc) {
        gc.setStroke(Color.RED);
        gc.strokeRoundRect(10, 10, 230, 230, 10, 10);
    }

    public static class MouseGestures {

        double orgSceneX, orgSceneY;
        double orgTranslateX, orgTranslateY;

        public void makeDraggable(Node node) {
            node.setOnMousePressed(circleOnMousePressedEventHandler);
            node.setOnMouseDragged(circleOnMouseDraggedEventHandler);
        }

        EventHandler<MouseEvent> circleOnMousePressedEventHandler = new EventHandler<MouseEvent>() {

            @Override
            public void handle(MouseEvent t) {

                orgSceneX = t.getSceneX();
                orgSceneY = t.getSceneY();

                if (t.getSource() instanceof Circle) {

                    Circle p = ((Circle) (t.getSource()));

                    orgTranslateX = p.getCenterX();
                    orgTranslateY = p.getCenterY();

                } else {

                    Node p = ((Node) (t.getSource()));

                    orgTranslateX = p.getTranslateX();
                    orgTranslateY = p.getTranslateY();

                }
            }
        };

        EventHandler<MouseEvent> circleOnMouseDraggedEventHandler = new EventHandler<MouseEvent>() {

            @Override
            public void handle(MouseEvent t) {

                double offsetX = t.getSceneX() - orgSceneX;
                double offsetY = t.getSceneY() - orgSceneY;

                double newTranslateX = orgTranslateX + offsetX;
                double newTranslateY = orgTranslateY + offsetY;

                if (t.getSource() instanceof Circle) {

                    Circle p = ((Circle) (t.getSource()));

                    p.setCenterX(newTranslateX);
                    p.setCenterY(newTranslateY);

                } else {

                    Node p = ((Node) (t.getSource()));

                    p.setTranslateX(newTranslateX);
                    p.setTranslateY(newTranslateY);

                }

            }
        };

    }

}
like image 171
Roland Avatar answered Oct 31 '22 10:10

Roland