JavaFX - 删除形状但不删除锚点

JavaFX - Shape Deletes But Anchor Points Do Not

在我的程序中,我有两个既可拖动又可调整大小的矩形。我添加了一个功能,允许我在两者之间 select 然后根据 selection 和按钮单击删除其中一个。

删除前:

删除后:

代码:

//Fields

private DraggingRectangle drag = new DraggingRectangle();
private List<Node> selectedShapes = new ArrayList<>();
@FXML
private AnchorPane container, container2;

//CreatingTheRectangle

if (treeview.getSelectionModel().getSelectedItem() == blackrect) {
  Rectangle rect = drag.createDraggableRectangle(200, 60, 200, 60);
  GraphicsContext gc = canvas.getGraphicsContext2D();            
  rect.setFill(Color.BLACK);
  container2.getChildren().addAll(rect);
  rect.setOnMouseClicked(e -> onShapeSelected(e));
}

//SelectingMethod

public void onShapeSelected(MouseEvent e) {
    Shape shape = (Shape) e.getSource();
    shape.setStyle("-fx-effect: dropshadow(three-pass-box, red, 10, 10, 0,           0);");
    if (!selectedShapes.contains(shape)) {
        selectedShapes.add(shape);
        System.out.println("Shape Selected:" + shape);
    } else {
        shape.setStyle("-fx-effect: null");
        selectedShapes.remove(shape);
    }

//DeletingMethod

 public void deleteButton(ActionEvent e) {
    deletebutton.setOnAction(a ->   container2.getChildren().removeAll(selectedShapes));
}

DraggableRectangle Class:

public class DraggingRectangle  {

public Rectangle createDraggableRectangle(double x, double y, double width, double height) {
    final double handleRadius = 20 ;
    final double handleRadius2 = 30 ;

    Rectangle rect = new Rectangle(x, y, width, height);

    // top left resize handle:
    Circle resizeHandleNW = new Circle(handleRadius, Color.RED);
    // bind to top left corner of Rectangle:
    resizeHandleNW.centerXProperty().bind(rect.xProperty());
    resizeHandleNW.centerYProperty().bind(rect.yProperty());

    // bottom right resize handle:
    Circle resizeHandleSE = new Circle(handleRadius, Color.RED);
    // bind to bottom right corner of Rectangle:
    resizeHandleSE.centerXProperty().bind(rect.xProperty().add(rect.widthProperty()));
    resizeHandleSE.centerYProperty().bind(rect.yProperty().add(rect.heightProperty()));

    // move handle:
    Circle moveHandle = new Circle(handleRadius2,Color.RED);
    moveHandle.setOpacity(0.0);
    // bind to bottom center of Rectangle:
    moveHandle.centerXProperty().bind(rect.xProperty().add(rect.widthProperty().divide(2)));
    moveHandle.centerYProperty().bind(rect.yProperty().add(rect.heightProperty().divide(2)));

    // force circles to live in same parent as rectangle:
    rect.parentProperty().addListener((obs, oldParent, newParent) -> {
        for (Circle c : Arrays.asList(resizeHandleNW, resizeHandleSE, moveHandle)) {
            Pane currentParent = (Pane)c.getParent();
            if (currentParent != null) {
                currentParent.getChildren().remove(c);
            }
            ((Pane)newParent).getChildren().add(c);
        }
    });

    Wrapper<Point2D> mouseLocation = new Wrapper<>();

    setUpDragging(resizeHandleNW, mouseLocation) ;
    setUpDragging(resizeHandleSE, mouseLocation) ;
    setUpDragging(moveHandle, mouseLocation) ;

    resizeHandleNW.setOnMouseDragged(event -> {
        if (mouseLocation.value != null) {
            double deltaX = event.getSceneX() - mouseLocation.value.getX();
            double deltaY = event.getSceneY() - mouseLocation.value.getY();
            double newX = rect.getX() + deltaX ;
            if (newX >= handleRadius
                    && newX <= rect.getX() + rect.getWidth() - handleRadius) {
                rect.setX(newX);
                rect.setWidth(rect.getWidth() - deltaX);
            }
            double newY = rect.getY() + deltaY ;
            if (newY >= handleRadius
                    && newY <= rect.getY() + rect.getHeight() - handleRadius) {
                rect.setY(newY);
                rect.setHeight(rect.getHeight() - deltaY);
            }
            mouseLocation.value = new Point2D(event.getSceneX(), event.getSceneY());
        }
    });

    resizeHandleSE.setOnMouseDragged(event -> {
        if (mouseLocation.value != null) {
            double deltaX = event.getSceneX() - mouseLocation.value.getX();
            double deltaY = event.getSceneY() - mouseLocation.value.getY();
            double newMaxX = rect.getX() + rect.getWidth() + deltaX ;
            if (newMaxX >= rect.getX()
                    && newMaxX <= rect.getParent().getBoundsInLocal().getWidth() - handleRadius) {
                rect.setWidth(rect.getWidth() + deltaX);
            }
            double newMaxY = rect.getY() + rect.getHeight() + deltaY ;
            if (newMaxY >= rect.getY()
                    && newMaxY <= rect.getParent().getBoundsInLocal().getHeight() - handleRadius) {
                rect.setHeight(rect.getHeight() + deltaY);
            }
            mouseLocation.value = new Point2D(event.getSceneX(), event.getSceneY());
        }
    });

    moveHandle.setOnMouseDragged(event -> {
        if (mouseLocation.value != null) {
            double deltaX = event.getSceneX() - mouseLocation.value.getX();
            double deltaY = event.getSceneY() - mouseLocation.value.getY();
            double newX = rect.getX() + deltaX ;
            double newMaxX = newX + rect.getWidth();
            if (newX >= handleRadius
                    && newMaxX <= rect.getParent().getBoundsInLocal().getWidth() - handleRadius) {
                rect.setX(newX);
            }
            double newY = rect.getY() + deltaY ;
            double newMaxY = newY + rect.getHeight();
            if (newY >= handleRadius
                    && newMaxY <= rect.getParent().getBoundsInLocal().getHeight() - handleRadius) {
                rect.setY(newY);
            }
            mouseLocation.value = new Point2D(event.getSceneX(), event.getSceneY());
        }

    });

    return rect ;
}

private void setUpDragging(Circle circle, Wrapper<Point2D> mouseLocation) {

    circle.setOnDragDetected(event -> {
        circle.getParent().setCursor(Cursor.CLOSED_HAND);
        mouseLocation.value = new Point2D(event.getSceneX(), event.getSceneY());
    });

    circle.setOnMouseReleased(event -> {
        circle.getParent().setCursor(Cursor.DEFAULT);
        mouseLocation.value = null ;
    });
}

static class Wrapper<T> { T value ; }


}

我意识到这与我添加矩形的列表有关,但不知道如何添加锚点。谢谢

异常:

Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: Children: duplicate children added: parent = AnchorPane[id=container2]
at javafx.scene.Parent.onProposedChange(Parent.java:454)
at com.sun.javafx.collections.VetoableListDecorator.remove(VetoableListDecorator.java:329)
at com.sun.javafx.collections.VetoableListDecorator.remove(VetoableListDecorator.java:221)
at Model.DraggingRectangle.lambda$createDraggableRectangle[=12=](DraggingRectangle.java:43)
at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:182)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
at javafx.beans.property.ReadOnlyObjectWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyObjectWrapper.java:176)
at javafx.beans.property.ReadOnlyObjectWrapper.fireValueChangedEvent(ReadOnlyObjectWrapper.java:142)
at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:146)
at javafx.scene.Node.setParent(Node.java:720)
at javafx.scene.Parent.onProposedChange(Parent.java:497)
at com.sun.javafx.collections.VetoableListDecorator.removeFromList(VetoableListDecorator.java:149)
at com.sun.javafx.collections.VetoableListDecorator.removeAll(VetoableListDecorator.java:264)
at Controller.NewLayoutController.lambda$deleteButton(NewLayoutController.java:261)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Node.fireEvent(Node.java:8411)
at javafx.scene.control.Button.fire(Button.java:185)
at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase.handle(BehaviorSkinBase.java:96)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase.handle(BehaviorSkinBase.java:89)
at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
at javafx.scene.Scene$MouseHandler.access00(Scene.java:3485)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:352)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:275)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent5(GlassViewEventHandler.java:388)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:387)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
at com.sun.glass.ui.View.notifyMouse(View.java:937)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null9(WinApplication.java:191)
at java.lang.Thread.run(Thread.java:745)

多边形

 public ObservableList<Anchor> createAnchorsPoly(Polygon polygon, final   ObservableList<Double> points) {}

polygon.parentProperty().addListener((obs, oldParent, newParent) -> {
            Platform.runLater(() -> {
                for (ObservableList<Double> a : Arrays.asList(points)) {
                    Pane currentParent = (Pane)oldParent;
                    if (currentParent != null) {
                        currentParent.getChildren().remove(a);
                    }
                    if (newParent != null) {
                        ((Pane)newParent).getChildren().add(a); <<Error!
                    }
                }
            });

替换

rect.parentProperty().addListener((obs, oldParent, newParent) -> {
    for (Circle c : Arrays.asList(resizeHandleNW, resizeHandleSE, moveHandle)) {
        Pane currentParent = (Pane)c.getParent();
        if (currentParent != null) {
            currentParent.getChildren().remove(c);
        }
        ((Pane)newParent).getChildren().add(c);
    }
});

rect.parentProperty().addListener((obs, oldParent, newParent) -> {
    Platform.runLater(() -> {
        for (Circle c : Arrays.asList(resizeHandleNW, resizeHandleSE, moveHandle)) {
            Pane currentParent = (Pane)oldParent;
            if (currentParent != null) {
                currentParent.getChildren().remove(c);
            }
            if (newParent != null) {
                ((Pane)newParent).getChildren().add(c);
            }
        }
    });
});