如何在JavaFX中使用其边框更改形状属性?

如何在JavaFX中使用形状的边框以更改其中一个属性 – 高度,宽度,半径等。

我尝试使用圆形的圆圈来调整半径,但我想知道我是否可以使用形状的边框来做。

这是我的自定义圈类:

public class NewCircle extends Circle { public NewCircle (double x, double y , double radius, Color colore){ super(x,y,radius); this.setFill(colore); this.setOnMousePressed(circleOnMousePressedEventHandler); this.setOnMouseDragged(circleOnMouseDraggedEventHandler); } double orgSceneX, orgSceneY; double orgTranslateX, orgTranslateY; EventHandler circleOnMouseClickedEventHandler = new EventHandler(){ @Override public void handle(MouseEvent t ){ } }; EventHandler circleOnMousePressedEventHandler = new EventHandler(){ @Override public void handle(MouseEvent t){ orgSceneX = t.getSceneX(); orgSceneY = t.getSceneY(); Node source = (Node) t.getSource(); orgTranslateX = ((Circle) (t.getSource())).getTranslateX(); orgTranslateY = ((Circle) (t.getSource())).getTranslateY(); ((Circle)t.getSource()).toFront();; } }; EventHandler circleOnMouseDraggedEventHandler = new EventHandler() { @Override public void handle(MouseEvent t) { Node source = (Node) t.getSource(); Bounds sceneBounds = source.getScene().getRoot().getLayoutBounds(); Bounds localBounds = source.getBoundsInLocal(); double offsetX = t.getSceneX() - orgSceneX; double offsetY = t.getSceneY() - orgSceneY; double newTranslateX = orgTranslateX + offsetX; double newTranslateY = orgTranslateY + offsetY; // restirct x movement to scene bounds if (offsetX >= 0) { if (localBounds.getMaxX() + newTranslateX > sceneBounds.getMaxX()) { newTranslateX = sceneBounds.getMaxX() - localBounds.getMaxX(); } } else { if (localBounds.getMinX() + newTranslateX = 0) { if (localBounds.getMaxY() + newTranslateY > sceneBounds.getMaxY()) { newTranslateY = sceneBounds.getMaxY() - localBounds.getMaxY(); } } else { if (localBounds.getMinY() + newTranslateY < 0) { newTranslateY = -localBounds.getMinY(); } } source.setTranslateX(newTranslateX); source.setTranslateY(newTranslateY); } }; } 

我在这里做的是在窗格上放几个形状,然后允许用户点击形状来选择它们。 使用边界框选择形状围绕形状(而不是边框​​)的边界。 边界框在其角落和侧面中心有锚点。 用户可以拖动边界框以移动选定的形状。 用户可以拖动锚点以调整所选形状的大小。

这是一些代码,因为要完成它需要做一些工作。 代码可以清理一下,但它是相对正常的。

调整

调整应用程序大小

 import javafx.application.Application; import javafx.geometry.Bounds; import javafx.scene.*; import javafx.scene.layout.Pane; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.scene.shape.Ellipse; import javafx.scene.shape.Rectangle; import javafx.scene.shape.StrokeType; import javafx.stage.Stage; public class ResizingSample extends Application { private Pane root; private Node selectedNode; public static void main(String[] args) throws Exception { launch(args); } @Override public void start(final Stage stage) throws Exception { Ellipse ellipse = new Ellipse(100, 100, 50, 50); ellipse.setFill(Color.AQUAMARINE); Rectangle rectangle = new Rectangle(200, 250, 100, 100); rectangle.setFill(Color.PALEGREEN); root = new Pane( ellipse, rectangle ); stage.setScene( new Scene( root, 400, 400, Color.ALICEBLUE ) ); stage.show(); root.setOnMouseClicked(event -> { final Parent parentNode = ((Node) event.getTarget()).getParent(); if (selectedNode != null && !(parentNode instanceof ResizingControl)) { root.getChildren().removeIf(candidate -> candidate instanceof ResizingControl); selectedNode = null; } }); makeSelectable(ellipse, rectangle); } private void makeSelectable(Node... nodes) { for (Node node: nodes) { node.setOnMouseClicked(event -> { if (selectedNode != node) { root.getChildren().removeIf(candidate -> candidate instanceof ResizingControl); selectedNode = node; node.toFront(); ResizingControl resizingControl = new ResizingControl(node); root.getChildren().add(resizingControl); } event.consume(); }); } } } class ResizingControl extends Group { private Node targetNode = null; private final Rectangle boundary = new Rectangle(); private Anchor topLeft = new Anchor(Color.GOLD, true, true, (oldX, oldY, newX, newY) -> { double newWidth = boundary.getWidth() - (newX - oldX); if (newWidth > 0) { boundary.setX(newX); boundary.setWidth(newWidth); } double newHeight = boundary.getHeight() - (newY - oldY); if (newHeight > 0) { boundary.setY(newY); boundary.setHeight(newHeight); } updateAnchorPositions(); resizeTargetNode(); }); private Anchor topCenter = new Anchor(Color.GOLD, false, true, (oldX, oldY, newX, newY) -> { double newHeight = boundary.getHeight() - (newY - oldY); if (newHeight > 0) { boundary.setY(newY); boundary.setHeight(newHeight); } updateAnchorPositions(); resizeTargetNode(); }); private Anchor topRight = new Anchor(Color.GOLD, true, true, (oldX, oldY, newX, newY) -> { double newWidth = boundary.getWidth() + (newX - oldX); if (newWidth > 0) { boundary.setWidth(newWidth); } double newHeight = boundary.getHeight() - (newY - oldY); if (newHeight > 0) { boundary.setY(newY); boundary.setHeight(newHeight); } updateAnchorPositions(); resizeTargetNode(); }); private Anchor rightCenter = new Anchor(Color.GOLD, true, false, (oldX, oldY, newX, newY) -> { double newWidth = boundary.getWidth() + (newX - oldX); if (newWidth > 0) { boundary.setWidth(newWidth); } updateAnchorPositions(); resizeTargetNode(); }); private Anchor bottomRight = new Anchor(Color.GOLD, true, true, (oldX, oldY, newX, newY) -> { double newWidth = boundary.getWidth() + (newX - oldX); if (newWidth > 0) { boundary.setWidth(newWidth); } double newHeight = boundary.getHeight() + (newY - oldY); if (newHeight > 0) { boundary.setHeight(newHeight); } updateAnchorPositions(); resizeTargetNode(); }); private Anchor bottomCenter = new Anchor(Color.GOLD, false, true, (oldX, oldY, newX, newY) -> { double newHeight = boundary.getHeight() + (newY - oldY); if (newHeight > 0) { boundary.setHeight(newHeight); } updateAnchorPositions(); resizeTargetNode(); }); private Anchor bottomLeft = new Anchor(Color.GOLD, true, true, (oldX, oldY, newX, newY) -> { double newWidth = boundary.getWidth() - (newX - oldX); if (newWidth > 0) { boundary.setX(newX); boundary.setWidth(newWidth); } double newHeight = boundary.getHeight() + (newY - oldY); if (newHeight > 0) { boundary.setHeight(newHeight); } updateAnchorPositions(); resizeTargetNode(); }); private Anchor leftCenter = new Anchor(Color.GOLD, true, false, (oldX, oldY, newX, newY) -> { double newWidth = boundary.getWidth() - (newX - oldX); if (newWidth > 0) { boundary.setX(newX); boundary.setWidth(newWidth); } updateAnchorPositions(); resizeTargetNode(); }); ResizingControl(Node targetNode) { this.targetNode = targetNode; attachBoundingRectangle(targetNode); attachAnchors(); boundary.toBack(); } private void attachBoundingRectangle(Node node) { Bounds bounds = node.getBoundsInParent(); boundary.setStyle( "-fx-stroke: forestgreen; " + "-fx-stroke-width: 2px; " + "-fx-stroke-dash-array: 12 2 4 2; " + "-fx-stroke-dash-offset: 6; " + "-fx-stroke-line-cap: butt; " + "-fx-fill: rgba(255, 228, 118, .5);" ); boundary.setX(bounds.getMinX()); boundary.setY(bounds.getMinY()); boundary.setWidth(bounds.getWidth()); boundary.setHeight(bounds.getHeight()); Util.makeDraggable(boundary, (oldX, oldY, newX, newY) -> { updateAnchorPositions(); relocateTargetNode(newX, newY); }); getChildren().add(boundary); } private void relocateTargetNode(double newX, double newY) { if (targetNode instanceof Ellipse) { Ellipse ellipse = (Ellipse) targetNode; ellipse.setCenterX(newX + ellipse.getRadiusX()); ellipse.setCenterY(newY + ellipse.getRadiusY()); } else if (targetNode instanceof Rectangle) { Rectangle rectangle = (Rectangle) targetNode; rectangle.setX(newX); rectangle.setY(newY); } } private void resizeTargetNode() { if (targetNode instanceof Ellipse) { Ellipse ellipse = (Ellipse) targetNode; ellipse.setRadiusX(boundary.getWidth() / 2); ellipse.setRadiusY(boundary.getHeight() / 2); relocateTargetNode(boundary.getX(), boundary.getY()); } else if (targetNode instanceof Rectangle) { Rectangle rectangle = (Rectangle) targetNode; rectangle.setWidth(boundary.getWidth()); rectangle.setHeight(boundary.getHeight()); relocateTargetNode(boundary.getX(), boundary.getY()); } } private void attachAnchors() { updateAnchorPositions(); getChildren().addAll( topLeft, topCenter, topRight, rightCenter, bottomRight, bottomCenter, bottomLeft, leftCenter ); } private void updateAnchorPositions() { topLeft.setCenterX(boundary.getX()); topLeft.setCenterY(boundary.getY()); topCenter.setCenterX(boundary.getX() + boundary.getWidth() / 2); topCenter.setCenterY(boundary.getY()); topRight.setCenterX(boundary.getX() + boundary.getWidth()); topRight.setCenterY(boundary.getY()); rightCenter.setCenterX(boundary.getX() + boundary.getWidth()); rightCenter.setCenterY(boundary.getY() + boundary.getHeight() / 2); bottomRight.setCenterX(boundary.getX() + boundary.getWidth()); bottomRight.setCenterY(boundary.getY() + boundary.getHeight()); bottomCenter.setCenterX(boundary.getX() + boundary.getWidth() / 2); bottomCenter.setCenterY(boundary.getY() + boundary.getHeight()); bottomLeft.setCenterX(boundary.getX()); bottomLeft.setCenterY(boundary.getY() + boundary.getHeight()); leftCenter.setCenterX(boundary.getX()); leftCenter.setCenterY(boundary.getY() + boundary.getHeight() / 2); } } interface DragHandler { void handle(double oldX, double oldY, double newX, double newY); } // a draggable anchor displayed around a point. class Anchor extends Circle { Anchor(Color color, boolean canDragX, boolean canDragY, DragHandler dragHandler) { super(0, 0, 5); setFill(color.deriveColor(1, 1, 1, 0.5)); setStroke(color); setStrokeWidth(2); setStrokeType(StrokeType.OUTSIDE); Util.enableDrag(this, canDragX, canDragY, dragHandler); } } class Util { // make a targetNode movable by dragging it around with the mouse. static void enableDrag(Circle node, boolean canDragX, boolean canDragY, DragHandler dragHandler) { final Delta dragDelta = new Delta(); node.setOnMousePressed(mouseEvent -> { // record a delta distance for the drag and drop operation. dragDelta.x = node.getCenterX() - mouseEvent.getX(); dragDelta.y = node.getCenterY() - mouseEvent.getY(); node.getScene().setCursor(Cursor.MOVE); }); node.setOnMouseReleased(mouseEvent -> { node.getScene().setCursor(Cursor.HAND); }); node.setOnMouseDragged(mouseEvent -> { double oldX = node.getCenterX(); double oldY = node.getCenterY(); double newX = mouseEvent.getX() + dragDelta.x; if (canDragX && newX > 0 && newX < node.getScene().getWidth()) { node.setCenterX(newX); } double newY = mouseEvent.getY() + dragDelta.y; if (canDragY && newY > 0 && newY < node.getScene().getHeight()) { node.setCenterY(newY); } newX = node.getCenterX(); newY = node.getCenterY(); if (dragHandler != null && (newX != oldX || newY != oldY)) { dragHandler.handle(oldX, oldY, newX, newY); } }); node.setOnMouseEntered(mouseEvent -> { if (!mouseEvent.isPrimaryButtonDown()) { node.getScene().setCursor(Cursor.HAND); } }); node.setOnMouseExited(mouseEvent -> { if (!mouseEvent.isPrimaryButtonDown()) { node.getScene().setCursor(Cursor.DEFAULT); } }); } // make a targetNode movable by dragging it around with the mouse. static void makeDraggable(Rectangle node, DragHandler dragHandler) { final Delta dragDelta = new Delta(); node.setOnMouseEntered(me -> { if (!me.isPrimaryButtonDown()) { node.getScene().setCursor(Cursor.HAND); } }); node.setOnMouseExited(me -> { if (!me.isPrimaryButtonDown()) { node.getScene().setCursor(Cursor.DEFAULT); } }); node.setOnMousePressed(me -> { if (me.isPrimaryButtonDown()) { node.getScene().setCursor(Cursor.DEFAULT); } dragDelta.x = me.getX() - node.getX(); dragDelta.y = me.getY() - node.getY(); node.getScene().setCursor(Cursor.MOVE); }); node.setOnMouseReleased(me -> { if (!me.isPrimaryButtonDown()) { node.getScene().setCursor(Cursor.DEFAULT); } }); node.setOnMouseDragged(me -> { double oldX = node.getX(); double oldY = node.getY(); node.setX(me.getX() - dragDelta.x); node.setY(me.getY() - dragDelta.y); double newX = node.getX(); double newY = node.getY(); if (dragHandler != null && (newX != oldX || newY != oldY)) { dragHandler.handle(oldX, oldY, newX, newY); } }); } // records relative x and y co-ordinates. private static class Delta { double x, y; } }