JavaFX VBox Layout



我用VBox作为布局编写了一段代码。我希望按钮出现在顶行,然后在 200x400 场景中绘制 2 条水平线,这些水平线应该在 y=200 和 300。但是输出显示了我给它的不同坐标处的线。

我知道这是因为我正在定义的布局。我的问题是这样的:

1)我可以以某种方式在保持相同布局的真实坐标上画线吗?

2) 如果不是,哪种 javafx 布局最适合此操作?

3)假设有一个菜单栏而不是那个按钮,那么哪种布局最合适?

package practise;
import java.util.Random;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
public class Practise extends Application {
    private int c = 0;
    @Override
    public void start(Stage primaryStage) {
        Button btn = new Button();
        VBox root = new VBox();
        Group group = new Group();
        final Line l1 = new Line(0,200,400,200);      
        final Line l2 = new Line(0,300,400,300);      
        btn.setText("Say 'Hello World'");
        btn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                System.out.println("Hello World!");
                }
            }
        );

        l1.setStroke(Color.YELLOW);
        l1.setStrokeWidth(2);
        l1.setLayoutX(0);
        l1.setLayoutY(0);
        l2.setStroke(Color.YELLOW);
        l2.setStrokeWidth(2);
        l2.setLayoutX(0);
        l2.setLayoutY(0);
        group.getChildren().add(l1);
        group.getChildren().add(l2);
        root.getChildren().add(btn);
        root.getChildren().add(group);
        Scene scene = new Scene(root, 400, 400, Color.WHITE);
        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }
}

1)是的,这是可能的。将 managed 属性设置为 false会导致父级不布局子项。不过,这不会使下一个节点位于线下方。

Button btn = new Button();
VBox root = new VBox();
final Line l1 = new Line(0, 200, 400, 200);
final Line l2 = new Line(0, 300, 400, 300);
l1.setManaged(false);
l2.setManaged(false);
btn.setText("Say 'Hello World'");
btn.setOnAction((ActionEvent event) -> {
    System.out.println("Hello World!");
});
l1.setStroke(Color.YELLOW);
l1.setStrokeWidth(2);
l2.setStroke(Color.YELLOW);
l2.setStrokeWidth(2);
root.getChildren().addAll(btn, l1, l2, rect);

2)

GridPane

允许指定对行大小的约束。

Button btn = new Button();
Rectangle rect = new Rectangle(400, 10);
GridPane root = new GridPane();
root.getRowConstraints().add(new RowConstraints(200));
final Line l1 = new Line(0, 0, 400, 0);
btn.setText("Say 'Hello World'");
btn.setOnAction((ActionEvent event) -> {
    System.out.println("Hello World!");
});
l1.setStroke(Color.YELLOW);
l1.setStrokeWidth(2);
root.addColumn(0, btn, l1, rect);

SplitPane

也可以通过一些调整来做到这一点。

Button btn = new Button();
Rectangle rect = new Rectangle(400, 10);
// wrap contents in resizeable Nodes
SplitPane root = new SplitPane(new Pane(btn), new Pane(rect));
// place divider in the middle
root.setDividerPositions(0.5);
root.setOrientation(Orientation.VERTICAL);
root.getStyleClass().add("line-split");
root.getStylesheets().add(getClass().getResource("style.css").toExternalForm());
root.skinProperty().addListener((observable, oldValue, newValue) -> {
    // don't allow resizing
    newValue.getNode().lookupAll(".split-pane-divider").stream().forEach(divider -> divider.setDisable(true));
});
btn.setText("Say 'Hello World'");
btn.setOnAction((ActionEvent event) -> {
    System.out.println("Hello World!");
});

.CSS

.line-split .split-pane-divider {
    -fx-min-height: 2;
    -fx-max-height: 2;
    -fx-background-color: yellow;
}

3)MenuBar也是Node。似乎没有理由将其与Button区别对待.

如果要设置绝对位置,则应使用锚窗格。仅将 VBox 更改为锚窗格即可工作。

相关内容

  • 没有找到相关文章

最新更新