Относительно позиционирования строки .. вы связали значения x и забыли связать значения y.
node.edge.startYProperty().bind(current.circle.centerYProperty());
node.edge.endYProperty().bind(node.circle.centerYProperty());
А что касается позиционирования текста, вам нужно переместить текст на половину его границ, чтобы расположить егов центр данной позиции. Приведенный ниже код может работать.
node.label.xProperty().bind(node.circle.centerXProperty().subtract(node.circle.radiusProperty().subtract(10))); // Your PADDING value
node.label.yProperty().bind(node.circle.centerYProperty().subtract(node.circle.radiusProperty().subtract(10))); // Your PADDING value
Если вы предоставите минимальный пример, я могу дать вам более точное решение.
Для каждой реализации может быть много способов. Ниже приведен один из подходов, которые я могу использовать по следующим причинам:
- группировать подобные вещи в одном классе
- избегать лишних узлов Circle
- Don 'не беспокоиться о расположении текста.
Это всего лишь мои взгляды, не уверен, что это поможет вам.
import javafx.application.Application;
import javafx.beans.binding.DoubleBinding;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Line;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class BinarySearchLayoutDemo extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
Pane root = new Pane();
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
InfoNode node1 = buildAndAddNode(root, null, "345785", 100, 100);
InfoNode node2 = buildAndAddNode(root, node1, "2356", 200, 200);
InfoNode node3 = buildAndAddNode(root, node1, "589", 50, 200);
InfoNode node4 = buildAndAddNode(root, node2, "478", 280, 300);
InfoNode node5 = buildAndAddNode(root, node2, "25", 150, 300);
}
private InfoNode buildAndAddNode(Pane root, InfoNode parentNode, String text, double x, double y) {
InfoNode node = new InfoNode(text);
node.setPosition(x, y);
root.getChildren().add(node);
if (parentNode != null) {
Line line = new Line();
line.startXProperty().bind(parentNode.centerXProperty());
line.startYProperty().bind(parentNode.centerYProperty());
line.endXProperty().bind(node.centerXProperty());
line.endYProperty().bind(node.centerYProperty());
root.getChildren().add(line);
line.toBack();
}
return node;
}
class InfoNode extends StackPane {
private double PADDING = 8;
private double x;
private double y;
public InfoNode(String txt) {
Text text = new Text(txt);
double size = getWidth(text) + (2 * PADDING);
setStyle("-fx-shape:\"M 0 0 m -5, 0 a 5,5 0 1,0 10,0 a 5,5 0 1,0 -10,0\";-fx-border-color:black;-fx-border-width:1px;-fx-background-color:yellow;");
setMinSize(size, size);
getChildren().add(text);
widthProperty().addListener((obs, old, val) -> setLayoutX(x - val.doubleValue() / 2));
heightProperty().addListener((obs, old, val) -> setLayoutY(y - val.doubleValue() / 2));
}
public DoubleBinding centerXProperty() {
return layoutXProperty().add(widthProperty().divide(2));
}
public DoubleBinding centerYProperty() {
return layoutYProperty().add(heightProperty().divide(2));
}
public void setPosition(double x, double y) {
this.x = x;
this.y = y;
setLayoutX(x - getWidth() / 2);
setLayoutY(y - getHeight() / 2);
}
private double getWidth(Text text) {
new Scene(new Group(text));
text.applyCss();
return text.getLayoutBounds().getWidth();
}
}
}