JavaFX to achieve the effect of dragging nodes

After reviewing the tree structure of data structure in school, I want to draw the tree using JavaFX. I want to make the node of the tree drag and drop. Here, I simply record the mouse drag of JavaFX.

Drag and drop is a common user interaction in GUI. It often reminds users that a node can be clicked by changing the mouse pointer into a gesture:

When the user clicks the mouse (to be exact, it means to press and hold the mouse), the mouse pointer will change to a cross to remind the user that the node can be dragged:

Both mouse pointer changes are simple, as long as they are set in the corresponding event processor:

public class DraggableDemo extends Application {
  private void draggable(Node node) {
    // 提示用户该结点可点击
    node.addEventHandler(MouseEvent.MOUSE_ENTERED,event -> node.setCursor(Cursor.HAND));
    node.addEventHandler(MouseEvent.MOUSE_EXITED,event -> node.setCursor(Cursor.DEFAULT));

    // 提示用户该结点可拖拽
    node.addEventHandler(MouseEvent.MOUSE_PRESSED,event -> node.setCursor(Cursor.MOVE));
    node.addEventHandler(MouseEvent.MOUSE_RELEASED,event -> node.setCursor(Cursor.DEFAULT));

    // ... 剩余代码 ...
  }
}

The node dragging is realized below, which is described with reference to the X axis:

In the figure, the unknown to be calculated is x (the variable in the y-axis direction is not considered temporarily), where x = layoutx + distancex. In addition, when the user presses the mouse, we need to cache the position coordinates of the pressing event. Next, we realize the node drag function. The calculation method of variable y is similar to that of X.

We first write an internal class position, which is specifically used to represent coordinates:

public class DraggableDemo extends Application {
  private static class Position {
    double x;
    double y;
  }
  // ... ...
}

Then we rewrite the original draggable (node node) method:

private void draggable(Node node) {
  final Position pos = new Position();

  // 提示用户该结点可点击
  node.addEventHandler(MouseEvent.MOUSE_ENTERED,event -> node.setCursor(Cursor.HAND));
  node.addEventHandler(MouseEvent.MOUSE_EXITED,event -> node.setCursor(Cursor.DEFAULT));

  // 提示用户该结点可拖拽
  node.addEventHandler(MouseEvent.MOUSE_PRESSED,event -> {
   node.setCursor(Cursor.MOVE);

    // 当按压事件发生时,缓存事件发生的位置坐标
   pos.x = event.getX();
   pos.y = event.getY();
  });
  node.addEventHandler(MouseEvent.MOUSE_RELEASED,event -> node.setCursor(Cursor.DEFAULT));

  // 实现拖拽功能
  node.addEventHandler(MouseEvent.MOUSE_DRAGGED,event -> {
    double distanceX = event.getX() - pos.x;
    double distanceY = event.getY() - pos.y;

    double x = node.getLayoutX() + distanceX;
    double y = node.getLayoutY() + distanceY;

    // 计算出 x、y 后将结点重定位到指定坐标点 (x,y)
    node.relocate(x,y);
  });
}

Next, write a function to create a node:

private Pane generateCircleNode(String data) {
  Pane node = new StackPane();

  Circle circle = new Circle(20);
  circle.setStyle("-fx-fill: rgb(51,184,223)");

  Text text = new Text(data);
  text.setStyle("-fx-fill: rgb(93,93,93);-fx-font-weight: bold;");

  node.getChildren().addAll(circle,text);

  return node;
}
// 进行测试
@Override
public void start(Stage primaryStage) throws Exception {
  Pane root = new Pane();
  Scene scene = new Scene(root,800,800);
  primaryStage.setScene(scene);
  primaryStage.show();

  Pane node1 = generateCircleNode("1");
  Pane node2 = generateCircleNode("2");

  node1.relocate(50,50);
  node2.relocate(300,150);

  draggable(node1);
  draggable(node2);

  root.getChildren().addAll(node1,node2);
}

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

Assuming that two nodes have some relationship, we usually connect the two nodes. The starting coordinate of the connected line should be bound with the central coordinate of one of the nodes; The end coordinates of a straight line should be bound to the center coordinates of another node.

// 进行测试
@Override
public void start(Stage primaryStage) throws Exception {
  Pane root = new Pane();
  Scene scene = new Scene(root,800);
  primaryStage.setScene(scene);
  primaryStage.show();

  Pane node1 = generateCircleNode("1");
  Pane node2 = generateCircleNode("2");

  // 将结点重定位到任意位置
  node1.relocate(50,150);

  // 使结点可拖拽
  draggable(node1);
  draggable(node2);

  // 创建直线
  Line line = new Line();

  // 将直线的起点坐标与 node1 的中心坐标进行绑定
  line.startXproperty().bind(node1.layoutXproperty().add(node1.widthproperty().divide(2)));
  line.startYproperty().bind(node1.layoutYproperty().add(node1.heightproperty().divide(2)));

  // 将直线的终点坐标与 node2 的中心坐标进行绑定
  line.endXproperty().bind(node2.layoutXproperty().add(node2.widthproperty().divide(2)));
  line.endYproperty().bind(node2.layoutYproperty().add(node2.heightproperty().divide(2)));

  root.getChildren().addAll(line,node1,node2);
}

Finally, code summary and effect display:

public class DraggableDemo extends Application {

  private static class Position {
    double x;
    double y;
  }

  private void draggable(Node node) {
    final Position pos = new Position();

    // 提示用户该结点可点击
    node.addEventHandler(MouseEvent.MOUSE_ENTERED,event -> {
      node.setCursor(Cursor.MOVE);

      // 当按压事件发生时,缓存事件发生的位置坐标
      pos.x = event.getX();
      pos.y = event.getY();
    });
    node.addEventHandler(MouseEvent.MOUSE_RELEASED,event -> node.setCursor(Cursor.DEFAULT));

    // 实现拖拽功能
    node.addEventHandler(MouseEvent.MOUSE_DRAGGED,event -> {
      double distanceX = event.getX() - pos.x;
      double distanceY = event.getY() - pos.y;

      double x = node.getLayoutX() + distanceX;
      double y = node.getLayoutY() + distanceY;

      // 计算出 x、y 后将结点重定位到指定坐标点 (x,y)
      node.relocate(x,y);
    });
  }

  private Pane generateCircleNode(String data) {
    Pane node = new StackPane();

    Circle circle = new Circle(20);
    circle.setStyle("-fx-fill: rgb(51,223)");

    Text text = new Text(data);
    text.setStyle("-fx-fill: rgb(93,93);-fx-font-weight: bold;");

    node.getChildren().addAll(circle,text);

    return node;
  }

  @Override
  public void start(Stage primaryStage) throws Exception {
    Pane root = new Pane();
    Scene scene = new Scene(root,800);
    primaryStage.setScene(scene);
    primaryStage.show();

    Pane node1 = generateCircleNode("1");
    Pane node2 = generateCircleNode("2");

    // 将结点重定位到任意位置
    node1.relocate(50,50);
    node2.relocate(300,150);

    // 使结点可拖拽
    draggable(node1);
    draggable(node2);

    // 创建直线
    Line line = new Line();

    // 将直线的起点坐标与 node1 的中心坐标进行绑定
    line.startXproperty().bind(node1.layoutXproperty().add(node1.widthproperty().divide(2)));
    line.startYproperty().bind(node1.layoutYproperty().add(node1.heightproperty().divide(2)));

    // 将直线的终点坐标与 node2 的中心坐标进行绑定
    line.endXproperty().bind(node2.layoutXproperty().add(node2.widthproperty().divide(2)));
    line.endYproperty().bind(node2.layoutYproperty().add(node2.heightproperty().divide(2)));

    root.getChildren().addAll(line,node2);
  }

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

The above is the whole content of this article. I hope it will help you in your study, and I hope you will support us a lot.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>