1

I have a javafx program that generates a canvas where a user can draw an Ellipse. I am using the press down, drag and release technique for the mouse. However I want to be able to scale the shape in size from the top left corner of the shape (much like a Rectangle is scaled) rather than its center. Is there any suggestions to how I could achieve this?

@Override
public void start(Stage ellipseStage) {

    //Create ellipse
    ellipsePane = new Pane();
    ellipsePane.setMinSize(600,600);

    ellipsePane.setOnMousePressed(e -> {
        if (e.getButton() == MouseButton.PRIMARY) {
            ellipse = new Ellipse();
            ellipse.setCenterX(e.getX());
            ellipse.setCenterY(e.getY());
            ellipse.setStroke(Color.ORANGE);
            ellipse.setFill(Color.BLACK);
            ellipsePane.getChildren().add(ellipse);
        }
        //if we double click
        if (e.getClickCount() == 2) {
            ellipse = null;
        }
    });

    //When the mouse is dragged the ellipse expands
    ellipsePane.setOnMouseDragged(e -> {
        if (ellipse != null) {
            ellipse.setRadiusX(e.getX() - ellipse.getCenterX());
            ellipse.setRadiusY(e.getY() - ellipse.getCenterY());
        }
    });

    Scene scene = new Scene(ellipsePane);
    ellipseStage.setScene(scene);
    ellipseStage.show();
}

public static void main(String[] args) {
    launch(args);
}}
  • You're setting the radius based on the position of the click, relative to the center. What if you used `getLayoutX()` or `getCenterX() - getRadiusX()/2` to get the edge position? – matt May 24 '19 at 09:26

2 Answers2

1

One option is to keep track of the location of the original mouse press, then set the center X/Y properties of the Ellipse to always be the midpoint between the origin and where the mouse is currently (i.e. where it's dragged). The radii would be half the distance between the origin and the current location as well. Here's an example:

import javafx.application.Application;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Ellipse;
import javafx.stage.Stage;

public class Main extends Application {

    private Pane pane;
    private Point2D origin;
    private Ellipse ellipse;

    @Override
    public void start(Stage primaryStage) {
        pane = new Pane();
        pane.setOnMousePressed(this::handleMousePressed);
        pane.setOnMouseDragged(this::handleMouseDragged);
        pane.setOnMouseReleased(this::handleMouseReleased);

        primaryStage.setScene(new Scene(pane, 600.0, 400.0));
        primaryStage.show();
    }

    private void handleMousePressed(MouseEvent event) {
        event.consume();

        origin = new Point2D(event.getX(), event.getY());
        ellipse = new Ellipse(event.getX(), event.getY(), 0.0, 0.0);
        pane.getChildren().add(ellipse);
    }

    private void handleMouseDragged(MouseEvent event) {
        event.consume();

        ellipse.setCenterX((origin.getX() + event.getX()) / 2.0);
        ellipse.setCenterY((origin.getY() + event.getY()) / 2.0);
        ellipse.setRadiusX(Math.abs(event.getX() - origin.getX()) / 2.0);
        ellipse.setRadiusY(Math.abs(event.getY() - origin.getY()) / 2.0);
    }

    private void handleMouseReleased(MouseEvent event) {
        event.consume();

        ellipse = null;
        origin = null;
    }

}
Slaw
  • 37,820
  • 8
  • 53
  • 80
0

So I presume what you mean is that when you drag the ellipse, the edge position changes but you want the edge position to stay the same and the center to move.

ellipsePane.setOnMouseDragged(e -> {
    if (ellipse != null) {

        double x0 = ellipse.getCenterX() - ellipse.getRadiusX();
        double y0 = ellipse.getCenterY() - ellipse.getRadiusY();

        //the new radii
        double rxp = e.getX() - x0;
        double ryp = e.getY() - y0;

        //the new center positions. to keep the origin the same.
        double cx = x0 + rxp;
        double cy = y0 + ryp;

        ellipse.setRadiusX(rxp);
        ellipse.setRadiusY(ryp);
        ellipse.setCenterX(cx);
        ellipse.setCenterY(cy);

    }
});
matt
  • 10,892
  • 3
  • 22
  • 34