如何设置多边形的可拖动边界 - JavaFX

时间:2016-12-16 19:37:13

标签: java javafx

我有一个多边形,可以根据需要调整大小,并根据需要在场景中拖动/移动。但是,我的问题是如何阻止它被拖过按钮或我的树视图列表?这是我的代码:

public Polygon cfp(ActionEvent event) throws IOException {

    Polygon fp = new Polygon();
    ObjectProperty<Point2D> mousePosition = new SimpleObjectProperty<>();
    //Set the anchor points for the template layout
    fp.getPoints().setAll(
            350d, 50d,
            700d, 50d,
            1050d, 50d,
            1050d, 350d,
            1050d, 650d,
            700d, 650d,
            350d, 650d,
            350d, 350d

    );

    //Allow the Floor plan to be draggable around the screen
    fp.setOnMousePressed(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent event) {
            mousePosition.set(new Point2D(event.getSceneX(), event.getSceneY()));
        }
    });

    fp.setOnMouseDragged(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent event) {
            double deltaX = event.getSceneX() - mousePosition.get().getX();
            double deltaY = event.getSceneY() - mousePosition.get().getY();
            fp.setLayoutX(fp.getLayoutX()+deltaX);
            fp.setLayoutY(fp.getLayoutY()+deltaY);
            mousePosition.set(new Point2D(event.getSceneX(), event.getSceneY()));
        }
    });
    //Set the colour and properties of the template layout
    fp.setStroke(Color.DARKRED);
    fp.setStrokeWidth(4);
    fp.setStrokeLineCap(StrokeLineCap.ROUND);
    fp.setFill(Color.MINTCREAM);
    container.getChildren().add(fp);
    container.getChildren().addAll(createAnchors(fp, fp.getPoints()));
    return fp;
}

private ObservableList<Anchor> createAnchors(Polygon polygon, final ObservableList<Double> points) {
    ObservableList<Anchor> anchors = FXCollections.observableArrayList();
    for (int i = 0; i < points.size(); i += 2) {

        final int idx = i;
        DoubleProperty xProperty = new ListWriteDoubleProperty(points, i);
        DoubleProperty yProperty = new ListWriteDoubleProperty(points, i + 1);

        //Bind the anchors to the polygon, so if its moved so are they
        Anchor anchor = new Anchor(Color.BLACK, xProperty, yProperty);
        anchor.layoutXProperty().bindBidirectional(polygon.layoutXProperty());
        anchor.layoutYProperty().bindBidirectional(polygon.layoutYProperty());

        xProperty.addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> ov, Number oldX, Number x) {
                points.set(idx, (double) x);
            }
        });

        yProperty.addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> ov, Number oldY, Number y) {
                points.set(idx + 1, (double) y);
            }
        });
        anchors.add(anchor);
    }
    return anchors;
}

//Creating circles to mark the anchor points to help users know where to modify from
class Anchor extends Circle {
    private final DoubleProperty x, y;

    Anchor(Color color, DoubleProperty x, DoubleProperty y) {
        super(x.get(), y.get(), 5);
        setFill(color.deriveColor(1, 1, 1, 0.5));
        setStroke(color);
        setStrokeWidth(2);
        setStrokeType(StrokeType.OUTSIDE);

        this.x = x;
        this.y = y;

        x.bind(centerXProperty());
        y.bind(centerYProperty());
        enableDrag();
    }

    //Make the circle node movable with mouse drag
    private void enableDrag() {
        final Delta dragDelta = new Delta();
        setOnMousePressed(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                // record a delta distance for the drag and drop operation.
                dragDelta.x = getCenterX() - mouseEvent.getX();
                dragDelta.y = getCenterY() - mouseEvent.getY();
                getScene().setCursor(Cursor.MOVE);
            }
        });
        setOnMouseReleased(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                getScene().setCursor(Cursor.HAND);
            }
        });
        setOnMouseDragged(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                double newX = mouseEvent.getX() + dragDelta.x;
                if (newX > 0 && newX < getScene().getWidth()) {
                    setCenterX(newX);
                }
                double newY = mouseEvent.getY() + dragDelta.y;
                if (newY > 0 && newY < getScene().getHeight()) {
                    setCenterY(newY);
                }
            }
        });
        setOnMouseEntered(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                if (!mouseEvent.isPrimaryButtonDown()) {
                    getScene().setCursor(Cursor.HAND);
                }
            }
        });
        setOnMouseExited(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                if (!mouseEvent.isPrimaryButtonDown()) {
                    getScene().setCursor(Cursor.DEFAULT);
                }
            }
        });
    }

    // records the x and y co-ordinates.
    private class Delta {
        double x, y;
    }

}

这是我的问题:

enter image description here

多边形生成的场景有一个Anchor窗格,树视图位于HBox中,如果有帮助的话,那么按钮也是如此。

1 个答案:

答案 0 :(得分:2)

发生了什么

检查锚点的拖动点是基于场景尺寸而不是多边形的父容器的尺寸。

如何修复

将支票更改为基于父容器尺寸。

自:

setOnMouseDragged(new EventHandler<MouseEvent>() {
    @Override
    public void handle(MouseEvent mouseEvent) {
        double newX = mouseEvent.getX() + dragDelta.x;
        if (newX > 0 && newX < getScene().getWidth()) {
            setCenterX(newX);
        }
        double newY = mouseEvent.getY() + dragDelta.y;
        if (newY > 0 && newY < getScene().getHeight()) {
            setCenterY(newY);
        }
    }
});

要:

setOnMouseDragged(new EventHandler<MouseEvent>() {
    @Override
    public void handle(MouseEvent mouseEvent) {
        double newX = mouseEvent.getX() + dragDelta.x;
        if (newX > 0 && newX < getParent().getLayoutBounds().getWidth()) {
            setCenterX(newX);
        }
        double newY = mouseEvent.getY() + dragDelta.y;
        if (newY > 0 && newY < getParent().getLayoutBounds().getHeight()) {
            setCenterY(newY);
        }
    }
});

确保您的父级是可调整大小的父级(例如,窗格而不是组),否则父级不会自动扩展以填充可放置多边形的可用区域。

其他问题

如果调整场景大小以使多边形可以渲染的区域小于多边形的大小,那么多边形仍会溢出可用边界(因为它们现在缩小了小于多边形的大小) )。有几种方法可以处理这种情况。

  1. 您可以将多边形放在ScrollPane中,以便用户可以在当前可查看区域太小的情况下滚动。这可能是首选的解决方案,但实施起来要复杂一点(并不是你提出的问题)。我目前还没有为此提供示例代码。
  2. 您可以将剪辑应用于父容器,以便它不会在可见区域之外绘制。例如,如果多边形的容器窗格名为polyPane:

    Rectangle clip = new Rectangle();
    clip.widthProperty().bind(polyPane.widthProperty());
    clip.heightProperty().bind(polyPane.heightProperty());
    polyPane.setClip(clip);
    
  3. 源自StackOverflow的内容需要attribution