2016-09-23 90 views
0

我有兩個節點。我想單擊一個節點,將光標拖到另一個節點,並在光標釋放後用線連接兩個節點。JavaFx通過拖放連接兩個子節點與一條線

我已經設置了所有的EventHandlers - 拖放行作品,但它不綁定到第二個節點。

public class LinkHandler { 
    static Node hoverNode; 
} 

該類用於查找光標懸停在哪個節點上。

private void setLinkHandlers(Node node) { 
    Line line = new Line(); 
    this.getChildren().add(line); 

    // On mouse hover, set LinkHandler.hoverNode 
    node.setOnMouseDragEntered((MouseEvent mouseEvent) -> { 
     LinkHandler.setHoverNode(node); 
     System.out.println(node); 
    }); 

    // On mouse exit, remove LinkHandler.hoverNode 
    node.setOnMouseDragExited((MouseEvent mouseEvent) -> { 
     // PLEASE NOTE: I have tried commenting and uncommenting the line below. Neither works. 
     // LinkHandler.setHoverNode(null); 
    }); 

    // On mouse press, set Line startpoint 
    node.setOnMousePressed((MouseEvent mouseEvent) -> { 
     // Stop BorderPane from being dragged 
     LinkHandler.isConnecting = true; 

     // Bind startpoint to node position 
     line.startXProperty().bind(node.layoutXProperty()); 
     line.startYProperty().bind(node.layoutYProperty()); 
    }); 

    // On mouse released, either bind Line to LinkHandler.hoverNode, or remove if hoverNode = null 
    node.setOnMouseReleased((MouseEvent mouseEvent) -> { 
     // Allow BorderPane to be dragged again 
     LinkHandler.isConnecting = false; 

     // If there is a node to connect to... 
     if(LinkHandler.getHoverNode() != null) { 
      // Bind end position to the node's position 
      line.endXProperty().bind(LinkHandler.getHoverNode().layoutXProperty()); 
      line.endYProperty().bind(LinkHandler.getHoverNode().layoutYProperty()); 
     } else { 
      // Otherwise print error 
      System.out.println("Not hovering over a node. Cannot create connection."); 
     } 
    }); 

    // Temporarily bind Line endpoint to mouse position. 
    node.setOnMouseDragged((MouseEvent mouseEvent) -> { 
     line.setEndX(mouseEvent.getX()); 
     line.setEndY(mouseEvent.getY()); 
    }); 
} 

這是一個很大的代碼,所以我會試着總結一下吧:

  • 當dragEntered,設置LinkHandler.hoverNode此節點
  • 當dragExit,設置LinkHandler.hoverNode到空
  • 的mousePressed時,結合線開始位置到該節點的位置
  • 當的mouseDragged,臨時設置線端部位置到mousePosition
  • 當mouseReleased時,將行結束位置綁定到LinkerHandler.hoverNode位置,或者刪除Line is hoverNode爲null。

我認爲問題就出在這個片段:

// On mouse hover, set LinkHandler.hoverNode 
    node.setOnMouseDragEntered((MouseEvent mouseEvent) -> { 
     LinkHandler.setHoverNode(node); 
     System.out.println(node); 
    }); 

    // On mouse exit, remove LinkHandler.hoverNode 
    node.setOnMouseDragExited((MouseEvent mouseEvent) -> { 
     // LinkHandler.setHoverNode(null); 
    }); 

我不認爲這是正確的得到所謂的。此代碼適用的節點是BorderPane的子節點,它具有它自己的onMouseDrag功能< <這可能也會導致問題。

在此先感謝,對不起,如果這個問題有點含糊。我試圖具體。

回答

1

請注意,您永遠不會初始化完整的拖動,因此事件永遠不會傳遞到拖動的起始節點以外的節點。要改變這種情況,請爲起始節點調用startFullDrag()

下面的例子演示貼緊線的Circle S上的中心:一`setOnDragDetected`事件處理程序中

public static Circle createCircle(double x, double y) { 
    return new Circle(x, y, 20, Color.BLACK.deriveColor(0, 1, 1, 0.5)); 
} 

@Override 
public void start(Stage primaryStage) { 

    Node[] circles = new Node[]{ 
     createCircle(40, 40), 
     createCircle(240, 40), 
     createCircle(40, 240), 
     createCircle(240, 240) 
    }; 
    Pane root = new Pane(circles); 

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

    for (Node n : circles) { 
     // register handlers 
     n.setOnDragDetected(startHandler); 
     n.setOnMouseDragReleased(dragReleaseHandler); 
     n.setOnMouseDragEntered(dragEnteredHandler); 

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

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

    Scene scene = new Scene(root, 280, 280); 

    primaryStage.setScene(scene); 
    primaryStage.show(); 
} 
+0

我在'startFullDrag adeded()'命令,它仍然不會對工作一些原因。 'setOnMouseDragEntered'永遠不會觸發。 – user3668541

相關問題