如何使用一条线连接两个节点

时间:2017-07-29 17:25:04

标签: java javafx javafx-2 javafx-8

如何将位于第一个容器中的节点连接到第二个容器中的另一个节点,即如果我有一个其中包含子节点的窗格,我将如何将其连接到另一个窗格子节点,I&#39 ;我只是管理连接是同一个容器的节点,但这不是我需要的,我想要这样的东西。

enter code here
public class Main extends Application {

   static Pane root = new Pane();


   @Override
   public void start(Stage primaryStage) throws Exception{

      Circuit c1 = new Circuit(10,10);
      Circuit c2 = new Circuit(200,10);
      Circuit c3 = new Circuit(10,200);
      Circuit c4 = new Circuit(200,200);

      root.getChildren().addAll(c1, c2, c3, c4);

      primaryStage.setScene(new Scene(root, 300, 275));
      primaryStage.show();
  }


   public static void main(String[] args) {
      launch(args);
   }
 }

电路类

enter code here

 import static sample.Main.root;

 public class Circuit  extends Pane{

Circuit(int LOCATION_X, int LOCATION_Y){
    setStyle("-fx-background-color: red");
    setPrefSize(150,150);

    setLayoutX(LOCATION_X);
    setLayoutY(LOCATION_Y);

    createCircle cir = new createCircle();

    cir.setLayoutX(75);
    cir.setLayoutY(75);

    // register handlers
    cir.setOnDragDetected(startHandler);
    cir.setOnMouseDragReleased(dragReleaseHandler);
    cir.setOnMouseDragEntered(dragEnteredHandler);

    // add info allowing to identify this node as drag source/target
    cir.setUserData(Boolean.TRUE);

    getChildren().add(cir);



    root.setOnMouseReleased(evt -> {
        // mouse released outside of a target -> remove line
        root.getChildren().remove(startHandler.line);
        startHandler.line = null;
    });
    root.setOnMouseDragged(evt -> {
        if (startHandler.line != null) {
            Node pickResult = evt.getPickResult().getIntersectedNode();
            if (pickResult == null || pickResult.getUserData() != Boolean.TRUE) {
                // mouse outside of target -> set line end to mouse position
                startHandler.line.setEndX(evt.getX());
                startHandler.line.setEndY(evt.getY());
            }
        }
    });
}

    class DragStartHandler implements EventHandler<MouseEvent> {

       public Line line;

       @Override
       public void handle(MouseEvent event) {
           if (line == null) {
               Node sourceNode = (Node) event.getSource();
               line = new Line();
               Bounds bounds = sourceNode.getBoundsInParent();

               // start line at center of node
               line.setStartX((bounds.getMinX() + bounds.getMaxX()) / 2);
               line.setStartY((bounds.getMinY() + bounds.getMaxY()) / 2);
               line.setEndX(line.getStartX());
               line.setEndY(line.getStartY());
               sourceNode.startFullDrag();
               root.getChildren().add(0, line);
           }
       }
   }

   DragStartHandler startHandler = new DragStartHandler();
   EventHandler<MouseDragEvent> dragReleaseHandler = evt -> {
       if (evt.getGestureSource() == evt.getSource()) {
           // remove line, if it starts and ends in the same node
           root.getChildren().remove(startHandler.line);
       }
       evt.consume();
       startHandler.line = null;
   };
   EventHandler<MouseEvent> dragEnteredHandler = evt -> {
       if (startHandler.line != null) {
           // snap line end to node center
           Node node = (Node) evt.getSource();
           Bounds bounds = node.getBoundsInParent();
           startHandler.line.setEndX((bounds.getMinX()+bounds.getMaxX())/2); 

           startHandler.line.setEndY((bounds.getMinY()+bounds.getMaxY())/2);
        }
       };

 }

电线将拉出并连接到

的点
enter code here

 public class createCircle extends Circle {

createCircle(){

   super(25, Color.BLACK.deriveColor(0, 1, 1, 0.5));
}

}

enter image description here

1 个答案:

答案 0 :(得分:1)

您正在混合坐标系。

Bounds bounds = sourceNode.getBoundsInParent();

将在sourceNode父级的坐标系中为您提供sourceNode的边界,这将是当前Circuit实例(如果我正确读取您的代码) 。但是,您正在使用这些边界来计算放置在根节点中的线的坐标,因此您需要根坐标系中的坐标。

您可以通过执行类似

的操作来转换坐标
Bounds boundsInScene = sourceNode.localToScene(sourceNode.getBoundsInLocal());
Bounds boundsInRoot = root.sceneToLocal(boundsInScene);

现在boundsInRoot代表sourceNode坐标系中root的范围,因此您可以使用它来计算线的坐标。您可能需要在整个代码中进行类似的转换。