這不能通過綁定完成,因爲綁定將目標屬性綁定到特定值,並且不會將該值限制在某個範圍。
要達到預期的效果,您必須自己將移動到onMouseDragged
事件處理程序中。下面的代碼將Circle
移動到矩形上鼠標位置的最近點:
@Override
public void start(Stage primaryStage) {
Circle circle = new Circle(200, 100, 10, Color.RED);
Rectangle rect = new Rectangle(200, 100, 200, 300);
rect.setFill(null);
rect.setStroke(Color.BLACK);
rect.setStrokeWidth(3);
Pane root = new Pane(rect, circle);
circle.setOnMouseDragged(evt -> {
Circle c = (Circle) evt.getSource();
Point2D mousePosition = new Point2D(evt.getX(), evt.getY());
Point2D targetPosition = closestPosition(c.localToParent(mousePosition), rect);
c.setCenterX(targetPosition.getX());
c.setCenterY(targetPosition.getY());
});
Scene scene = new Scene(root, 600, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
private static class Container {
final double distance;
final double targetX;
final double targetY;
public Container(double coord1, double coord2, double targetX, double targetY) {
this.distance = Math.abs(coord1 - coord2);
this.targetX = targetX;
this.targetY = targetY;
}
public double getDistance() {
return distance;
}
}
public static Point2D closestPosition(Point2D point, Rectangle rect) {
double minX = rect.getX();
double maxX = minX + rect.getWidth();
double minY = rect.getY();
double maxY = minY + rect.getHeight();
double x = point.getX();
double y = point.getY();
boolean outsideXRange = x < minX || x > maxX;
boolean outsideYRange = y < minY || y > maxY;
if (!outsideXRange && !outsideYRange) {
// place point on the edge closest to the point and keep other coordinate
Container container = Stream.of(
new Container(x, minX, minX, y),
new Container(x, maxX, maxX, y),
new Container(y, minY, x, minY),
new Container(y, maxY, x, maxY)
).min(Comparator.comparingDouble(Container::getDistance)).get();
return new Point2D(container.targetX, container.targetY);
} else {
return new Point2D(
outsideXRange ? dMin(x, minX, maxX) : x,
outsideYRange ? dMin(y, minY, maxY) : y);
}
}
private static double dMin(double target, double value1, double value2) {
return Math.abs(target - value1) < Math.abs(target - value2) ? value1 : value2;
}