Я пытаюсь создать редактор UML.Я нашел много вариантов кода, которые берут круги из библиотеки JavaFX Shape и делают их перетаскиваемыми с линией, которая следует за их центром.Я думал, что смогу взять логику из этих программ и применить ее к любой панели (в своей итерации я выбрал FlowPane).Тем не менее, когда я делал это, линия оставалась только на месте и не следовала за перетаскиваемой панелью.
Я пробовал несколько итераций, используя разные типы панелей, и пытался использовать прямоугольник, но одна и та же проблема продолжала происходить.Конечная точка линии внутри фигуры Rectangle не будет перетаскиваться вместе с ней.
(Примечание. Большая часть этого кода взята из примера перетаскиваемых кружков и линий на сайте www.java2s.com. Мой код состоит из createBoxи функции connectBox)
Моя функция «создать перетаскиваемый прямоугольник»:
private FlowPane createBox (double posX, double posY) {
FlowPane node = new FlowPane();
node.setPrefSize(100, 100);
node.setStyle(
"-fx-background-color: black; "
+ "-fx-text-fill: black; "
+ "-fx-border-color: black;");
node.setLayoutX(posX);
node.setLayoutY(posY);
node.setCursor(Cursor.HAND);
node.setOnMousePressed((t) -> {
orgSceneX = t.getSceneX();
orgSceneY = t.getSceneY();
});
node.setOnMouseDragged((t) -> {
double offsetX = t.getSceneX() - orgSceneX;
double offsetY = t.getSceneY() - orgSceneY;
Pane c = (Pane) (t.getSource());
c.setLayoutX(c.getLayoutX() + offsetX);
c.setLayoutY(c.getLayoutY() + offsetY);
orgSceneX = t.getSceneX();
orgSceneY = t.getSceneY();
});
return node;
}
Предоставленная функция перетаскивания по кругу и линии:
private Circle createCircle(double x, double y, double r, Color color) {
Circle circle = new Circle(x, y, r, color);
circle.setCursor(Cursor.HAND);
circle.setOnMousePressed((t) -> {
orgSceneX = t.getSceneX();
orgSceneY = t.getSceneY();
Circle c = (Circle) (t.getSource());
c.toFront();
});
circle.setOnMouseDragged((t) -> {
double offsetX = t.getSceneX() - orgSceneX;
double offsetY = t.getSceneY() - orgSceneY;
Circle c = (Circle) (t.getSource());
c.setCenterX(c.getCenterX() + offsetX);
c.setCenterY(c.getCenterY() + offsetY);
orgSceneX = t.getSceneX();
orgSceneY = t.getSceneY();
});
return circle;
}
private Line connect(Circle c1, Circle c2) {
Line line = new Line();
line.startXProperty().bind(c1.centerXProperty());
line.startYProperty().bind(c1.centerYProperty());
line.endXProperty().bind(c2.centerXProperty());
line.endYProperty().bind(c2.centerYProperty());
line.setStrokeWidth(1);
line.setStrokeLineCap(StrokeLineCap.BUTT);
line.getStrokeDashArray().setAll(1.0, 4.0);
return line;
}
Моя линияФункция соединения (между моими «прямоугольниками» и кружком):
private Line connectBox(FlowPane c1, Circle c2) {
Line line = new Line();
line.startXProperty().bind(c1.widthProperty().divide(2).add(c1.getLayoutX()));
line.startYProperty().bind(c1.heightProperty().divide(2).add(c1.getLayoutY()));
line.endXProperty().bind(c2.centerXProperty());
line.endYProperty().bind(c2.centerYProperty());
line.setStrokeWidth(1);
line.setStrokeLineCap(StrokeLineCap.BUTT);
line.getStrokeDashArray().setAll(1.0, 4.0);
return line;
}
Запуск программы:
@Override
public void start(Stage primaryStage) {
Group root = new Group();
Scene scene = new Scene(root, 500, 260);
// circles
Circle redCircle = createCircle(100, 50, 30, Color.RED);
Circle blueCircle = createCircle(20, 150, 20, Color.BLUE);
Circle greenCircle = createCircle(40, 100, 40, Color.GREEN);
FlowPane box1 = createBox(100, 130);
Line line1 = connect(redCircle, blueCircle);
Line line2 = connect(redCircle, greenCircle);
Line line3 = connect(greenCircle, blueCircle);
Line line4 = connectBox(box1, blueCircle);
// add the circles
root.getChildren().add(redCircle);
root.getChildren().add(blueCircle);
root.getChildren().add(greenCircle);
root.getChildren().add(box1);
// add the lines
root.getChildren().add(line1);
root.getChildren().add(line2);
root.getChildren().add(line3);
root.getChildren().add(line4);
// bring the circles to the front of the lines
redCircle.toFront();
blueCircle.toFront();
greenCircle.toFront();
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}