JavaFx通过拖放将两个子节点连接到一条线
我有两个节点。我想单击一个节点,将光标拖到另一个节点上,释放光标后用一条线连接两个节点 我已经设置了所有eventhandler——拖放行是可行的,但它不会绑定到第二个节点JavaFx通过拖放将两个子节点连接到一条线,java,user-interface,javafx,nodes,drag,Java,User Interface,Javafx,Nodes,Drag,我有两个节点。我想单击一个节点,将光标拖到另一个节点上,释放光标后用一条线连接两个节点 我已经设置了所有eventhandler——拖放行是可行的,但它不会绑定到第二个节点 public class LinkHandler { static Node hoverNode; } 此类用于查找光标悬停在哪个节点上 private void setLinkHandlers(Node node) { Line line = new Line(); this.getChildre
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());
});
}
这是大量代码,因此我将尝试对其进行总结:
- 拖动代理后,将LinkHandler.hoverNode设置为此节点
- dragExit时,将LinkHandler.hoverNode设置为null
- 按下鼠标时,将线起始位置绑定到此节点位置
- 当鼠标标记时,临时将“行结束位置”设置为“鼠标位置”
- 释放鼠标后,将行结束位置绑定到LinkerHandler.hoverNode位置,或删除行为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功能请注意,您从未初始化完全拖动,因此事件从未传递到拖动的开始节点以外的节点。要更改此设置,请为开始节点调用
startFullDrag()
以下示例演示如何将线捕捉到圆的中心:
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();
}
公共静态圆createCircle(双x,双y){
返回新的圆(x,y,20,Color.BLACK.deriveColor(0,1,1,0.5));
}
@凌驾
公共无效开始(阶段primaryStage){
节点[]圆=新节点[]{
createCircle(40,40),
createCircle(240,40),
createCircle(40240),
createCircle(240240)
};
窗格根=新窗格(圆圈);
类DragStartHandler实现EventHandler{
公共线路;
@凌驾
公共无效句柄(MouseeEvent事件){
如果(行==null){
Node sourceNode=(Node)event.getSource();
行=新行();
Bounds Bounds=sourceNode.getBoundsInParent();
//节点中心的起始线
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,行);
}
}
}
DragStartHandler startHandler=新的DragStartHandler();
EventHandler DragreeLeaseHandler=evt->{
if(evt.getGestureSource()==evt.getSource()){
//删除在同一节点中开始和结束的线
root.getChildren().remove(startHandler.line);
}
evt.consume();
startHandler.line=null;
};
EventHandler dragEnteredHandler=evt->{
if(startHandler.line!=null){
//将线端点捕捉到节点中心
Node Node=(Node)evt.getSource();
Bounds=node.getBoundsInParent();
startHandler.line.setEndX((bounds.getMinX()+bounds.getMaxX())/2);
startHandler.line.setEndY((bounds.getMinY()+bounds.getMaxY())/2);
}
};
用于(节点n:圆){
//寄存器处理程序
n、 检测到SetOnDrag(startHandler);
n、 setOnMouseDragReleased(dragReleaseHandler);
n、 setOnMouseDragEntered(dragEnteredHandler);
//添加允许将此节点标识为拖动源/目标的信息
n、 setUserData(Boolean.TRUE);
}
root.setOnMouseReleased(evt->{
//鼠标在目标外释放->删除线
root.getChildren().remove(startHandler.line);
startHandler.line=null;
});
root.setonMouseDrawed(evt->{
if(startHandler.line!=null){
节点pickResult=evt.getPickResult().getIntersectedNode();
if(pickResult==null | | pickResult.getUserData()!=Boolean.TRUE){
//鼠标移到目标之外->将线端设置为鼠标位置
startHandler.line.setEndX(evt.getX());
startHandler.line.setEndY(evt.getY());
}
}
});
场景=新场景(根,280,280);
初级阶段。场景(场景);
primaryStage.show();
}
我在setOnDragDetected
事件处理程序中加入了startFullDrag()
命令,但由于某些原因,它仍然无法工作setOnMouseDragEntered
从不点火。