我想用一条线连接两个节点(从第一个的中心到第二个的中心).
初步想法:
假设两个节点存在于场景图中的某处
>线条作为装饰器,不应该是可选的
>如果Node Bounds改变,Line应该被更新
如何实现这一点?有人可以指出方向吗?
解决方法
此响应中的代码基于问题的答案:
CubicCurve JavaFX
以下示例:
假设涉及的所有节点都是兄弟姐妹.
>确保连接线不能通过调用setMouseTransparent(true)上线.
>随着锚节点被拖动,自动更新线路连接两个锚节点的中心.
import javafx.application.Application; import javafx.beans.property.*; import javafx.event.EventHandler; import javafx.scene.*; import javafx.scene.input.MouseEvent; import javafx.scene.paint.Color; import javafx.scene.shape.*; import javafx.stage.Stage; /** Example of dragging anchors around to manipulate a line. */ public class LineManipulator extends Application { public static void main(String[] args) throws Exception { launch(args); } @Override public void start(final Stage stage) throws Exception { DoubleProperty startX = new SimpleDoubleProperty(100); DoubleProperty startY = new SimpleDoubleProperty(100); DoubleProperty endX = new SimpleDoubleProperty(300); DoubleProperty endY = new SimpleDoubleProperty(200); Anchor start = new Anchor(Color.PALEGREEN,startX,startY); Anchor end = new Anchor(Color.TOMATO,endX,endY); Line line = new BoundLine(startX,startY,endY); stage.setTitle("Line Manipulation Sample"); stage.setScene(new Scene(new Group(line,start,end),400,Color.ALICEBLUE)); stage.show(); } class BoundLine extends Line { BoundLine(DoubleProperty startX,DoubleProperty startY,DoubleProperty endX,DoubleProperty endY) { startXProperty().bind(startX); startYProperty().bind(startY); endXProperty().bind(endX); endYProperty().bind(endY); setStrokeWidth(2); setStroke(Color.GRAY.deriveColor(0,1,0.5)); setStrokeLineCap(StrokeLineCap.BUTT); getStrokeDashArray().setAll(10.0,5.0); setMouseTransparent(true); } } // a draggable anchor displayed around a point. class Anchor extends Circle { Anchor(Color color,DoubleProperty x,DoubleProperty y) { super(x.get(),y.get(),10); setFill(color.deriveColor(1,0.5)); setStroke(color); setStrokeWidth(2); setStrokeType(StrokeType.OUTSIDE); x.bind(centerXProperty()); y.bind(centerYProperty()); enableDrag(); } // make a node movable by dragging it around with the mouse. 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 relative x and y co-ordinates. private class Delta { double x,y; } } }
上面的代码是基于一个圆,所以很容易跟踪圆的centerX和centerY属性.
对于任意形状的节点,您可以使用以下代码来跟踪其父级中心属性:
class Center { private ReadOnlyDoubleWrapper centerX = new ReadOnlyDoubleWrapper(); private ReadOnlyDoubleWrapper centerY = new ReadOnlyDoubleWrapper(); public Center(Node node) { calcCenter(node.getBoundsInParent()); node.boundsInParentProperty().addListener(new ChangeListener<Bounds>() { @Override public void changed( ObservableValue<? extends Bounds> observableValue,Bounds oldBounds,Bounds bounds ) { calcCenter(bounds); } }); } private void calcCenter(Bounds bounds) { centerX.set(bounds.getMinX() + bounds.getWidth() / 2); centerY.set(bounds.getMinY() + bounds.getHeight() / 2); } ReadOnlyDoubleProperty centerXProperty() { return centerX.getReadOnlyProperty(); } ReadOnlyDoubleProperty centerYProperty() { return centerY.getReadOnlyProperty(); } }
Anchor start = new Anchor(Color.PALEGREEN,startY); Anchor end = new Anchor(Color.TOMATO,endY); Center startCenter = new Center(start); Center endCenter = new Center(end); Line line = new BoundLine( startCenter.centerXProperty(),startCenter.centerYProperty(),endCenter.centerXProperty(),endCenter.centerYProperty() );
如果要跟踪场景中的任意节点,而不仅仅是兄弟节点,您可能需要查看node.getLayoutBounds和node.getLocalToSceneTransform的功能.