Zuerst müssen Sie uns sagen, was ist Ihr "reservierter Platz"? Wenn es sich um ein Canvas handelt, können Sie Formen mit Canvas GraphicsContext zeichnen.
Andernfalls, wenn Sie in einem Bereich mit Layout arbeiten, müssen Sie wissen, ob die Komponenten verwaltet werden oder nicht. Zum Beispiel in einem Fenster oder AnchorPane des Knotens automatisches Layout deaktiviert ist, so müssen Sie ihre layoutX und layoutY selbst spezifizieren (+ Knoten Abmessungen) wie:
node.setLayoutX(12);
node.setLayoutY(222);
node.setPrefWidth(500);
node.setPrefHeight(500);
Wenn Sie eine Scheibe wie VBox verwenden, die die Verwaltung Layout seiner Knoten müssen Sie festlegen, dass die Knoten innerhalb des Bereichs nicht verwaltet werden, damit Sie bestimmte Transformationen anwenden können. Sie können das tun nur, indem:
node.setManaged(false)
ich nicht empfehlen Sie Leinwand zu verwenden, verursachen die Formen der Handhabung sehr schwierig sein wird, zum Beispiel, wenn Sie etwas entfernen müssen, müssen Sie wahrscheinlich alles löschen und neu zu zeichnen nur die sichtbare Formen.
Nun, ich hatte so hier einige Zeit ist ein kleines Beispiel (Es ist vielleicht nicht die optimale Lösung sein, aber Sie können nehmen als Referenz)
Graphtest
import java.util.ArrayList;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
public class GraphTest extends Application {
private double orgSceneX, orgSceneY;
private double orgTranslateX, orgTranslateY;
private Group root = new Group();
@Override
public void start(Stage primaryStage) throws Exception {
GraphNode node1 = createNode("A", 100, 100, Color.RED);
GraphNode node2 = createNode("B", 300, 200, Color.GREEN);
GraphNode node3 = createNode("C", 80, 300, Color.PURPLE);
connectNodes(node1, node2, "C1");
connectNodes(node3, node1, "C2");
connectNodes(node3, node2, "C3");
root.getChildren().addAll(node1, node2, node3);
primaryStage.setScene(new Scene(root, 400, 400));
primaryStage.show();
}
private void connectNodes(GraphNode node1, GraphNode node2, String edgeText) {
Line edgeLine = new Line(node1.getCenterX(), node1.getCenterY(), node2.getCenterX(), node2.getCenterY());
Label edgeLabel = new Label(edgeText);
node1.addNeighbor(node2);
node2.addNeighbor(node1);
node1.addEdge(edgeLine, edgeLabel);
node2.addEdge(edgeLine, edgeLabel);
root.getChildren().addAll(edgeLine, edgeLabel);
}
private GraphNode createNode(String nodeName, double xPos, double yPos, Color color) {
GraphNode node = new GraphNode(nodeName, xPos, yPos, color);
node.setOnMousePressed(circleOnMousePressedEventHandler);
node.setOnMouseDragged(circleOnMouseDraggedEventHandler);
return node;
}
EventHandler<MouseEvent> circleOnMousePressedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
orgSceneX = t.getSceneX();
orgSceneY = t.getSceneY();
GraphNode node = (GraphNode) t.getSource();
orgTranslateX = node.getTranslateX();
orgTranslateY = node.getTranslateY();
}
};
EventHandler<MouseEvent> circleOnMouseDraggedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
double offsetX = t.getSceneX() - orgSceneX;
double offsetY = t.getSceneY() - orgSceneY;
double newTranslateX = orgTranslateX + offsetX;
double newTranslateY = orgTranslateY + offsetY;
GraphNode node = (GraphNode) t.getSource();
node.setTranslateX(newTranslateX);
node.setTranslateY(newTranslateY);
updateLocations(node);
}
};
private void updateLocations(GraphNode node) {
ArrayList<GraphNode> connectedNodes = node.getConnectedNodes();
ArrayList<Line> edgesList = node.getEdges();
for (int i = 0; i < connectedNodes.size(); i++) {
GraphNode neighbor = connectedNodes.get(i);
Line l = edgesList.get(i);
l.setStartX(node.getCenterX());
l.setStartY(node.getCenterY());
l.setEndX(neighbor.getCenterX());
l.setEndY(neighbor.getCenterY());
}
}
public static void main(String[] args) {
launch(args);
}
}
GraphNode
import java.util.ArrayList;
import javafx.beans.binding.DoubleBinding;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
public class GraphNode extends StackPane {
private Circle circle;
private Label text;
private ArrayList<GraphNode> connectedNodesList = new ArrayList<>();
private ArrayList<Line> edgesList = new ArrayList<>();
private ArrayList<Label> edgesLabelList = new ArrayList<>();
private double radius = 50.0;
public GraphNode(String name, double xPos, double yPos, Color color) {
circle = new Circle(radius, color);
text = new Label(name);
text.setTextFill(Color.WHITE);
setLayoutX(xPos);
setLayoutY(yPos);
getChildren().addAll(circle, text);
layout();
}
public void addNeighbor(GraphNode node) {
connectedNodesList.add(node);
}
public void addEdge(Line edgeLine, Label edgeLabel) {
edgesList.add(edgeLine);
edgesLabelList.add(edgeLabel);
// If user move the node we should translate the edge labels as well
// one way of doing that is by make a custom binding to the layoutXProperty as well
// as to layoutYProperty. We will listen for changes to the currentNode translate properties
// and for changes of our neighbor.
edgeLabel.layoutXProperty().bind(new DoubleBinding() {
{
bind(translateXProperty());
bind(connectedNodesList.get(connectedNodesList.size() - 1).translateXProperty());
}
@Override
protected double computeValue() {
// We find the center of the line to translate the text
double width = edgeLine.getEndX() - edgeLine.getStartX();
return edgeLine.getStartX() + width/2.0;
}
});
edgeLabel.layoutYProperty().bind(new DoubleBinding() {
{
bind(translateYProperty());
bind(connectedNodesList.get(connectedNodesList.size() - 1).translateYProperty());
}
@Override
protected double computeValue() {
double width = edgeLine.getEndY() - edgeLine.getStartY();
return edgeLine.getStartY() + width/2.0;
}
});
}
public ArrayList<GraphNode> getConnectedNodes() {
return connectedNodesList;
}
public ArrayList<Line> getEdges() {
return edgesList;
}
public double getX() {
return getLayoutX() + getTranslateX();
}
public double getY() {
return getLayoutY() + getTranslateY();
}
public double getCenterX() {
return getX() + radius;
}
public double getCenterY() {
return getY() + radius;
}
}
Und der Ausgang würde so aussehen:
Sie können die Knoten mit der Maus bewegen und Sie werden sehen, dass alle Etiketten, die die Formen Standorte folgen (Ciclo, Linien)
Bitte aktualisieren Sie Ihre Frage ein kleines (runnable) Beispiel zu geben, was du hast es schon getan. – JKostikiadis