如何用JavaFX绘制一条线

时间:2015-04-15 14:46:09

标签: java-8 javafx-8

我有以下代码,我尝试在两个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();

Screenshot

1 个答案:

答案 0 :(得分:2)

直到第一个脉冲(即直到实际执行布局)才计算布局边界。解决此问题的最佳方法是使用绑定。

此外,您正在使用标签的局部边界,而不是相对于线所在容器的边界。您需要进行适当的转换。

我不清楚您要尝试连接的内容,但此示例会将label1label3连接起来:

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);
    }
}

使用这种技术,即使标签在用户调整窗口大小时移动(或出于其他原因),该线也会保持连接标签。