我正在尝试为二进制搜索树编写一个程序,该程序会将圆圈放在JavaFX的窗格中,然后将圆圈与直线连接起来,使其看起来像二进制搜索树。我可以使圆出现在窗格中,但是正在创建的线保持在顶部,并且不会从父圆的中心到新圆的中心。我也希望文本在圆圈内居中,但我也无法使其正常工作。我在下面将我的代码以及我的输出和所需的输出一起发布了。
public boolean addNode(T addMe) {
boolean added = false;
MyNode current = root;
MyNode node = new MyNode(addMe, null, null);
if (root == null) {
root = node;
added = true;
} else {
while (added != true) {
if (addMe.compareTo(current.info) < 0) {
if (current.left == null) {
current.left = new MyNode(addMe, null, null);
added = true;
} else {
current = current.left;
}
} else {
if (current.right == null) {
current.right = new MyNode(addMe, null, null);
added = true;
} else {
current = current.right;
}
}
}
}
node.label = new Text("" + addMe);
node.label.setFont(new Font(16));
node.circle = encircle(node.label, node);
node.label.xProperty().bind(node.circle.centerXProperty());
node.label.yProperty().bind(node.circle.centerYProperty());
node.edge = new Line();
if(node != root) {
node.edge.startXProperty().bind(current.circle.centerXProperty());
node.edge.endXProperty().bind(node.circle.centerXProperty());
}
this.getChildren().add(node.edge);
node.edge.toBack();
node.circle.setOnMouseDragged(evt -> {
double mouseX = evt.getX(),
mouseY = evt.getY();
node.circle.setCenterX(mouseX);
node.circle.setCenterY(mouseY);
});
this.getChildren().addAll(node.circle, node.label);
return added;
}
private Circle encircle(Text text, MyNode node) {
node.circle = new Circle();
node.circle.setFill(Color.WHITE);
final double PADDING = 10;
node.circle.setRadius(getWidth(text) / 2 + PADDING);
if (node == root) {
node.circle.setStroke(Color.RED);
} else {
node.circle.setStroke(Color.BLACK);
}
return node.circle;
}
private int getWidth(Text text) {
new Scene(new Group(text));
text.applyCss();
return (int) text.getLayoutBounds().getWidth();
}
我的输出:My Output所需的输出:Desired Output
关于行定位。您绑定了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
如果您提供一个最小的示例,我可以为您提供更准确的解决方案。
每个实现都有很多方法。由于以下原因,以下是我可以使用的一种方法:
这些只是我的观点,不确定这是否可以帮助您。
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();
}
}
}