2016-04-29 77 views
0

我正在尝试将圆圈绑定到矩形的边缘,以便用户可以沿着其中一个边移动圆,但不能移动到其他任何位置。JavaFX将圆圈绑定到矩形的边缘?

至于现在,我结合圆的x和y坐标对矩形的坐标为这样:

Circle anchor = new Circle(); 
anchor.centerXProperty().bind(rectangle.xProperty().add(rectangle.widthProperty())); 
anchor.centerYProperty().bind(rectangle.yProperty().add(rectangle.heightProperty())); 

我将如何设置这个,所以我可以移动沿着边缘锚矩形的?

回答

0

这不能通过绑定完成,因为绑定将目标属性绑定到特定值,并且不会将该值限制在某个范围

要达到预期的效果,您必须自己将移动到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; 
}