如何使用 JavaFX 画线
How to draw a line with JavaFX
我有下面的代码,我尝试在两个 VBox 中创建 4 个标签,其中两个标签。我想用一条线将这些 VBox 连接起来。
我无法找到正确的 x,y 值来将线放在正确的位置。
@Override
public void start(Stage primaryStage) {
Group root = new Group();
Scene scene = new Scene(root);
Label label1 = new Label("Info \n 1");
label1.setStyle("-fx-border-color: black;-fx-padding: 10px;");
label1.setWrapText(true);
Label label2 = new Label("Info 2222222222222");
label2.setStyle("-fx-border-color: black;-fx-padding: 10px;");
label2.setWrapText(true);
VBox vbox1 = new VBox(5);
vbox1.setMaxWidth(50);
vbox1.getChildren().add(label1);
vbox1.getChildren().add(label2);
Label label3 = new Label("Info \n 3");
label3.setStyle("-fx-border-color: black;-fx-padding: 10px;");
label3.setWrapText(true);
Label label4 = new Label("Info 444444444444444444");
label4.setStyle("-fx-border-color: black;-fx-padding: 10px;");
label4.setWrapText(true);
VBox vbox2 = new VBox(5);
vbox2.setMaxWidth(50);
vbox2.getChildren().add(label3);
vbox2.getChildren().add(label4);
HBox hbox = new HBox(100);
hbox.getChildren().addAll(vbox1, vbox2);
Bounds bounds = label1.getBoundsInLocal();
double startX = bounds.getMaxX();
double startY = (bounds.getMaxY() - bounds.getMinY()) /2;
Line line = new Line(startX, startY, startX+100, startY);
line.setStrokeWidth(5);
line.setStroke(Color.BLACK);
Pane stack = new Pane();
stack.getChildren().addAll(hbox, line);
root.getChildren().addAll(stack);
primaryStage.setScene(scene);
primaryStage.show();
直到第一个脉冲(即实际执行布局)才会计算布局边界。解决此问题的最佳方法是使用绑定。
此外,您使用的是标签的局部边界,而不是相对于线条所在容器的边界。您需要进行适当的转换。
我不是很清楚你要连接什么,但这个例子会将 label1
连接到 label3
:
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.DoubleBinding;
import javafx.beans.binding.ObjectBinding;
import javafx.geometry.Bounds;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
public class ConnectedVBoxes extends Application {
@Override
public void start(Stage primaryStage) {
Group root = new Group();
Scene scene = new Scene(root);
Label label1 = new Label("Info \n 1");
label1.setStyle("-fx-border-color: black;-fx-padding: 10px;");
label1.setWrapText(true);
Label label2 = new Label("Info 2222222222222");
label2.setStyle("-fx-border-color: black;-fx-padding: 10px;");
label2.setWrapText(true);
VBox vbox1 = new VBox(5);
vbox1.setMaxWidth(50);
vbox1.getChildren().add(label1);
vbox1.getChildren().add(label2);
Label label3 = new Label("Info \n 3");
label3.setStyle("-fx-border-color: black;-fx-padding: 10px;");
label3.setWrapText(true);
Label label4 = new Label("Info 444444444444444444");
label4.setStyle("-fx-border-color: black;-fx-padding: 10px;");
label4.setWrapText(true);
VBox vbox2 = new VBox(5);
vbox2.setMaxWidth(50);
vbox2.getChildren().add(label3);
vbox2.getChildren().add(label4);
HBox hbox = new HBox(100);
hbox.getChildren().addAll(vbox1, vbox2);
Line line = new Line();
line.setStrokeWidth(5);
line.setStroke(Color.BLACK);
Pane stack = new Pane();
stack.getChildren().addAll(hbox, line);
ObjectBinding<Bounds> label1InStack = Bindings.createObjectBinding(() -> {
Bounds label1InScene = label1.localToScene(label1.getBoundsInLocal());
return stack.sceneToLocal(label1InScene);
}, label1.boundsInLocalProperty(), label1.localToSceneTransformProperty(), stack.localToSceneTransformProperty());
ObjectBinding<Bounds> label3InStack = Bindings.createObjectBinding(() -> {
Bounds label3InScene = label3.localToScene(label3.getBoundsInLocal());
return stack.sceneToLocal(label3InScene);
}, label3.boundsInLocalProperty(), label3.localToSceneTransformProperty(), stack.localToSceneTransformProperty());
DoubleBinding startX = Bindings.createDoubleBinding(() -> label1InStack.get().getMaxX(), label1InStack);
DoubleBinding startY = Bindings.createDoubleBinding(() -> {
Bounds b = label1InStack.get();
return b.getMinY() + b.getHeight() / 2 ;
}, label1InStack);
DoubleBinding endX = Bindings.createDoubleBinding(() -> label3InStack.get().getMinX(), label3InStack);
DoubleBinding endY = Bindings.createDoubleBinding(() -> {
Bounds b = label3InStack.get();
return b.getMinY() + b.getHeight() / 2 ;
}, label3InStack);
line.startXProperty().bind(startX);
line.startYProperty().bind(startY);
line.endXProperty().bind(endX);
line.endYProperty().bind(endY);
root.getChildren().addAll(stack);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
使用此技术,即使标签在用户调整 window 大小时(或出于其他原因)移动,线仍保持连接标签。
我有下面的代码,我尝试在两个 VBox 中创建 4 个标签,其中两个标签。我想用一条线将这些 VBox 连接起来。
我无法找到正确的 x,y 值来将线放在正确的位置。
@Override
public void start(Stage primaryStage) {
Group root = new Group();
Scene scene = new Scene(root);
Label label1 = new Label("Info \n 1");
label1.setStyle("-fx-border-color: black;-fx-padding: 10px;");
label1.setWrapText(true);
Label label2 = new Label("Info 2222222222222");
label2.setStyle("-fx-border-color: black;-fx-padding: 10px;");
label2.setWrapText(true);
VBox vbox1 = new VBox(5);
vbox1.setMaxWidth(50);
vbox1.getChildren().add(label1);
vbox1.getChildren().add(label2);
Label label3 = new Label("Info \n 3");
label3.setStyle("-fx-border-color: black;-fx-padding: 10px;");
label3.setWrapText(true);
Label label4 = new Label("Info 444444444444444444");
label4.setStyle("-fx-border-color: black;-fx-padding: 10px;");
label4.setWrapText(true);
VBox vbox2 = new VBox(5);
vbox2.setMaxWidth(50);
vbox2.getChildren().add(label3);
vbox2.getChildren().add(label4);
HBox hbox = new HBox(100);
hbox.getChildren().addAll(vbox1, vbox2);
Bounds bounds = label1.getBoundsInLocal();
double startX = bounds.getMaxX();
double startY = (bounds.getMaxY() - bounds.getMinY()) /2;
Line line = new Line(startX, startY, startX+100, startY);
line.setStrokeWidth(5);
line.setStroke(Color.BLACK);
Pane stack = new Pane();
stack.getChildren().addAll(hbox, line);
root.getChildren().addAll(stack);
primaryStage.setScene(scene);
primaryStage.show();
直到第一个脉冲(即实际执行布局)才会计算布局边界。解决此问题的最佳方法是使用绑定。
此外,您使用的是标签的局部边界,而不是相对于线条所在容器的边界。您需要进行适当的转换。
我不是很清楚你要连接什么,但这个例子会将 label1
连接到 label3
:
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.DoubleBinding;
import javafx.beans.binding.ObjectBinding;
import javafx.geometry.Bounds;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
public class ConnectedVBoxes extends Application {
@Override
public void start(Stage primaryStage) {
Group root = new Group();
Scene scene = new Scene(root);
Label label1 = new Label("Info \n 1");
label1.setStyle("-fx-border-color: black;-fx-padding: 10px;");
label1.setWrapText(true);
Label label2 = new Label("Info 2222222222222");
label2.setStyle("-fx-border-color: black;-fx-padding: 10px;");
label2.setWrapText(true);
VBox vbox1 = new VBox(5);
vbox1.setMaxWidth(50);
vbox1.getChildren().add(label1);
vbox1.getChildren().add(label2);
Label label3 = new Label("Info \n 3");
label3.setStyle("-fx-border-color: black;-fx-padding: 10px;");
label3.setWrapText(true);
Label label4 = new Label("Info 444444444444444444");
label4.setStyle("-fx-border-color: black;-fx-padding: 10px;");
label4.setWrapText(true);
VBox vbox2 = new VBox(5);
vbox2.setMaxWidth(50);
vbox2.getChildren().add(label3);
vbox2.getChildren().add(label4);
HBox hbox = new HBox(100);
hbox.getChildren().addAll(vbox1, vbox2);
Line line = new Line();
line.setStrokeWidth(5);
line.setStroke(Color.BLACK);
Pane stack = new Pane();
stack.getChildren().addAll(hbox, line);
ObjectBinding<Bounds> label1InStack = Bindings.createObjectBinding(() -> {
Bounds label1InScene = label1.localToScene(label1.getBoundsInLocal());
return stack.sceneToLocal(label1InScene);
}, label1.boundsInLocalProperty(), label1.localToSceneTransformProperty(), stack.localToSceneTransformProperty());
ObjectBinding<Bounds> label3InStack = Bindings.createObjectBinding(() -> {
Bounds label3InScene = label3.localToScene(label3.getBoundsInLocal());
return stack.sceneToLocal(label3InScene);
}, label3.boundsInLocalProperty(), label3.localToSceneTransformProperty(), stack.localToSceneTransformProperty());
DoubleBinding startX = Bindings.createDoubleBinding(() -> label1InStack.get().getMaxX(), label1InStack);
DoubleBinding startY = Bindings.createDoubleBinding(() -> {
Bounds b = label1InStack.get();
return b.getMinY() + b.getHeight() / 2 ;
}, label1InStack);
DoubleBinding endX = Bindings.createDoubleBinding(() -> label3InStack.get().getMinX(), label3InStack);
DoubleBinding endY = Bindings.createDoubleBinding(() -> {
Bounds b = label3InStack.get();
return b.getMinY() + b.getHeight() / 2 ;
}, label3InStack);
line.startXProperty().bind(startX);
line.startYProperty().bind(startY);
line.endXProperty().bind(endX);
line.endYProperty().bind(endY);
root.getChildren().addAll(stack);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
使用此技术,即使标签在用户调整 window 大小时(或出于其他原因)移动,线仍保持连接标签。