简体   繁体   English

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

[英]How to set draggable bounds for a polygon - JavaFX

I have a polygon that can be resized as required and dragged/moved around the scene as desired. 我有一个多边形,可以根据需要调整其大小,并根据需要在场景中拖动/移动它。 However, my question is how can I stop it from being dragged over buttons or my treeview list? 但是,我的问题是如何防止它被拖动到按钮或树状视图列表上方? Here is my code: 这是我的代码:

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;
    }

}

Here is my problem: 这是我的问题:

在此处输入图片说明

the scene where the polygon generates has an Anchor pane, the treeview is in a HBox and so are the buttons if that helps anyone. 多边形生成的场景具有“锚定”窗格,树视图位于HBox中,如果有帮助,则按钮也是如此。

What is Happening 怎么了

Your check for the drag points for the anchor are based upon the scene dimensions rather than the dimensions of the parent container of the polygon. 您检查锚点的拖动点是基于场景尺寸,而不是基于多边形父容器的尺寸。

How to Fix it 如何修复

Change your checks to be based upon the parent container dimensions. 将检查更改为基于父容器的尺寸。

From: 从:

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);
        }
    }
});

To: 至:

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);
        }
    }
});

Ensure that your parent is a resizable parent (eg a Pane and not a Group), otherwise the parent won't automatically expand to fill the available area in which the polygon can be placed. 确保父级是可调整大小的父级(例如,窗格而不是组),否则父级将不会自动展开以填充可放置多边形的可用区域。

Additional Concerns 其他问题

If you resize the scene so that the area in which the polygon can be rendered is smaller than the size of the polygon, then the polygon will still overflow the available bounds (as they have now shrunk smaller than the size of the polygon). 如果您调整场景的大小,以便可以在其中渲染多边形的区域小于多边形的大小,则多边形仍将溢出可用的边界(因为它们现在缩小为小于多边形的大小)。 There a couple of ways you could handle that situation. 有几种方法可以解决这种情况。

  1. You could place the polygon in a ScrollPane, so that the user can scroll around if the currently viewable area gets too small. 您可以将多边形放置在ScrollPane中,以便在当前可见区域过小时用户可以滚动。 This is probably the preferred solution, but is a bit more complicated to implement well (and it is isn't really the question you asked). 这可能是首选的解决方案,但实施起来要复杂一些(这并不是您真正提出的问题)。 I won't provide example code for this at the moment. 我目前不会提供示例代码。
  2. You can apply a clip to the parent container so that it does not draw outside the visible area. 您可以将一个剪辑应用于父容器,以使其不会在可见区域之外绘制。 For example if your container Pane for the polygon is named polyPane: 例如,如果您的多边形容器Pane名为polyPane:

     Rectangle clip = new Rectangle(); clip.widthProperty().bind(polyPane.widthProperty()); clip.heightProperty().bind(polyPane.heightProperty()); polyPane.setClip(clip); 

Content sourced from StackOverflow requires attribution . 来自StackOverflow的内容需要归因

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM