Domenico Santoro
Domenico Santoro

Reputation: 147

Draw a polygon in javafx

I'm trying to draw a polygon in javafx adding to its array of point the mouse coordinates. My problem is that I don't know how to make it stop when I click something else from the mouse left click.

Polygon polygon = new Polygon();
rootPane.setOnMouseClicked((MouseEvent mouseEvent) -> {
    do {
        polygon.getPoints().addAll(mouseEvent.getX(),mouseEvent.getY());
    } while(mouseEvent.getButton().equals(mouseEvent.isSecondaryButtonDown()));    
});
rootPane.getChildren().add(polygon);

Upvotes: 2

Views: 6197

Answers (2)

James_D
James_D

Reputation: 209684

You can create a reference to a polygon. If it's the first click, then the polygon will be null, so create a new one and add it to your pane. Then keep adding points until you get a right click, at which point you just set the polygon back to null, so that the next left click starts a new polygon again.

SSCCE:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;
import javafx.stage.Stage;

public class DrawPolygon extends Application {

    private Polygon currentPolygon ;

    @Override
    public void start(Stage primaryStage) {
        Pane rootPane = new Pane();
        rootPane.setMinSize(600, 600);
        rootPane.setOnMouseClicked(e -> {
            if (e.getButton() == MouseButton.PRIMARY) {
                if (currentPolygon == null) {
                    currentPolygon = new Polygon();
                    currentPolygon.setStroke(Color.BLACK);
                    rootPane.getChildren().add(currentPolygon);
                }
                currentPolygon.getPoints().addAll(e.getX(), e.getY());
            } else {
                currentPolygon = null ;
            }
        });
        Scene scene = new Scene(rootPane);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

You can play with various ideas around this to get different user experiences, e.g.

    rootPane.setOnMouseClicked(e -> {
        if (e.getButton() == MouseButton.PRIMARY) {
            if (currentPolygon == null) {
                currentPolygon = new Polygon();
                currentPolygon.getPoints().addAll(e.getX(), e.getY());
                currentPolygon.setStroke(Color.BLACK);
                rootPane.getChildren().add(currentPolygon);
            }
            currentPolygon.getPoints().addAll(e.getX(), e.getY());
        } else {
            currentPolygon = null ;
        }
    });
    rootPane.setOnMouseMoved(e -> {
        if (currentPolygon != null) {
            currentPolygon.getPoints().set(currentPolygon.getPoints().size()-2, e.getX());
            currentPolygon.getPoints().set(currentPolygon.getPoints().size()-1, e.getY());
        }
    });

Upvotes: 3

n247s
n247s

Reputation: 1912

The problem is that your code gets stuck in one single event. Even when you move your mouse, or release the mouse button, the values of that event instance you are working with, are not going to change.

Think of the event as a single state. When something important happens (in your case, a mousebutton is clicked), javafx will call your mouseEventHandler using a MouseEvent instance with the state of the mouse at that verry moment. When you click again javafx will create a new instance with new values, and call the eventHandler again.

In order to make this work, you need a different mouse event (or modify it slightly so its only setting a point on a single mouse click). You need to lose the (infinite) while-loop as it is both blocking the EventThread, and not working for the stuff you need it to do. So something like this might work a little better.

// this will add a point for every (secondary)mousebutton click
rootPane.setOnMouseClicked((MouseEvent me) -> {
    if(me.isSecondaryButtonDown())
        polygon.getPoints().addAll(me.getX(),me.getY());
     });

// this will add a point for every mousemovement while the secondary mousebutton is down.
rootPane.setOnMouseMoved((MouseEvent) me -> {
    if(me.isSecondaryButtonDown())
        polygon.getPoints().addAll(me.getX(),me.getY());
});

Now there is a MouseDragEvent, but thats mostly for moving data (like images and files), but I wouldnt recommend it. In your case it isnt much usefull, and its behavior is quit buggy still.

I hope this helped you in the right direction.

Upvotes: 1

Related Questions