我正在用javaFX製作應用程序。該應用程序由用戶創建一種「圖形」。 用戶通過一個按鈕創建一個節點(由具有JAVAFX圖形的圓圈創建)並將其關聯到一個變量,重複該過程,創建另一個節點,等等。現在我需要弄清楚如何在特定的保留空間內定義節點位置。顯然,在創建節點後,通過另一個按鈕,用戶創建與節點關聯的弧(由連接兩個節點的線創建),從而定義一個圖。 我的問題是,我不明白如何指示將在我的圖中作爲弧線的線的位置。使用javafx定義運行時的對象位置
請幫助我。我不是很有經驗,我正在努力解決這個問題。
我正在用javaFX製作應用程序。該應用程序由用戶創建一種「圖形」。 用戶通過一個按鈕創建一個節點(由具有JAVAFX圖形的圓圈創建)並將其關聯到一個變量,重複該過程,創建另一個節點,等等。現在我需要弄清楚如何在特定的保留空間內定義節點位置。顯然,在創建節點後,通過另一個按鈕,用戶創建與節點關聯的弧(由連接兩個節點的線創建),從而定義一個圖。 我的問題是,我不明白如何指示將在我的圖中作爲弧線的線的位置。使用javafx定義運行時的對象位置
請幫助我。我不是很有經驗,我正在努力解決這個問題。
首先你需要告訴我們你的「保留空間」是什麼?如果它是一個Canvas,那麼你可以用Canva的GraphicsContext繪製形狀。
Canvas canvas = new Canvas(300, 250);
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.fillOval(10, 60, 30, 30);
gc.fillArc(10, 110, 30, 30, 45, 240, ArcType.OPEN);
否則,如果你在一個佈局窗格內工作,你需要知道組件是否管理。例如,一個窗格或AnchorPane節點的自動佈局被禁用裏面,所以你需要自己指定其layoutX和layoutY(+節點的尺寸),如:
node.setLayoutX(12);
node.setLayoutY(222);
node.setPrefWidth(500);
node.setPrefHeight(500);
如果您使用的是像垂直框中,窗格,其管理您需要將窗格中的節點設置爲非託管,以便您應用特定的轉換,從而爲其節點佈局。你可以這樣做,只是通過設置:
node.setManaged(false)
,我不會建議你用帆布引起操作形狀會很辛苦,例如,如果您需要刪除你可能要清除一切,只有重繪的東西可見的形狀。
嗯,我有一些時間,所以這裏是一個小例子(它可能不是最佳的解決方案,但你可以採取作爲參照)
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;
}
}
而輸出將如下所示:
你可以用你的鼠標移動節點,你會看到所有的標籤將按照形狀位置(Cicle,線)
這是一個真實的例子,我用SCENE BUILDER做了所有的事情,但不幸的是我用可見和不可見的節點/弧來「玩」。 從某種意義上說,我繪製了5個節點和所有可能的鏈接,然後只使用戶需要的節點和弧可見。當然,這種策略並不好,我需要弄清楚如何將它們放置在該佈局中(而不是畫布)。圖片被分類。 1)https://ibb.co/kFLeOw 2)https://ibb.co/fcbawG 3)https://ibb.co/kuVeOw 4)https://ibb.co/kKB8GG 5) https://ibb.co/eeVeOw 6)https:// ibb。7)https://ibb.co/gHzjqb – Applefriend
所以你使用的佈局,在這種情況下,你需要將所有的節點設置爲.setManaged(false),然後以編程方式,你可以通過調用設置他們的位置setLayoutX&setLayoutY。當然,我會建議通過拖放實現移動看看這裏:http://java-buddy.blogspot.gr/2013/07/javafx-drag-and-move-something.html – JKostikiadis
我希望我可以做這樣,但對於兩個節點之間的弧線,我該怎麼做呢? – Applefriend
請更新您的問題給小(可運行)例如什麼你已經完成了。 – JKostikiadis