原文: http://zetcode.com/gui/javafx/layoutpanes/

JavaFX 教程的这一部分涵盖了节点的布局管理。 我们提到了以下布局窗格:FlowPaneHBoxBorderPaneAnchorPaneGridPaneMigPane。 另外,我们展示了如何使用Pane在绝对坐标中定位节点。

布局窗格是用于在 JavaFX 应用的场景图中灵活,动态地排列 UI 控件的容器。 调整窗口大小时,布局窗格会自动调整其位置和大小。

JavaFX 具有以下内置布局窗格:

  • FlowPane – 在环绕在窗格边界上的流中布置其子项。
  • HBox – 将其内容节点水平排列在一行中。
  • VBox – 将其内容节点垂直排列在单个列中。
  • AnchorPane – 将节点锚定到窗格的顶部,底部,左侧或中心。
  • BorderPane – 将其内容节点布置在顶部,底部,右侧,左侧或中央区域。
  • StackPane – 将其内容节点放置在从后到前的单个栈中。
  • TilePane – 将其内容节点放置在大小统一的布局单元或图块中。
  • GridPane – 将其内容节点放置在行和列的网格中。

为了创建更复杂的布局,可以在 JavaFX 应用中嵌套不同的容器。 除了GridPane之外,内置的布局管理器是非常基本的,不适用于更复杂的应用。 更复杂的布局应使用GridPane或第三方MigPane

绝对布局

Pane节点可用于在绝对坐标中定位节点。 复杂的布局应始终使用布局管理器创建; 绝对布局用于特定情况(例如,定位图或图像)。

AbsoluteLayoutEx.java

  1. package com.zetcode;
  2. import javafx.application.Application;
  3. import javafx.scene.Scene;
  4. import javafx.scene.layout.Pane;
  5. import javafx.scene.paint.Color;
  6. import javafx.scene.shape.Circle;
  7. import javafx.scene.shape.Line;
  8. import javafx.scene.shape.Rectangle;
  9. import javafx.stage.Stage;
  10. /**
  11. * ZetCode JavaFX tutorial
  12. *
  13. * This program positions three shapes
  14. * using absolute coordinates.
  15. *
  16. * Author: Jan Bodnar
  17. * Website: zetcode.com
  18. * Last modified: June 2015
  19. */
  20. public class AbsoluteLayoutEx extends Application {
  21. @Override
  22. public void start(Stage stage) {
  23. initUI(stage);
  24. }
  25. private void initUI(Stage stage) {
  26. Pane root = new Pane();
  27. Rectangle rect = new Rectangle(25, 25, 50, 50);
  28. rect.setFill(Color.CADETBLUE);
  29. Line line = new Line(90, 40, 230, 40);
  30. line.setStroke(Color.BLACK);
  31. Circle circle = new Circle(130, 130, 30);
  32. circle.setFill(Color.CHOCOLATE);
  33. root.getChildren().addAll(rect, line, circle);
  34. Scene scene = new Scene(root, 250, 220, Color.WHITESMOKE);
  35. stage.setTitle("Absolute layout");
  36. stage.setScene(scene);
  37. stage.show();
  38. }
  39. public static void main(String[] args) {
  40. launch(args);
  41. }
  42. }

此示例显示了三种形状:矩形,直线和圆形。 使用绝对坐标定位形状。

  1. Pane root = new Pane();

实例化了Pane节点。 要在绝对坐标中定位节点,我们使用Pane节点。

  1. Rectangle rect = new Rectangle(25, 25, 50, 50);

创建一个Rectangle形状。 前两个参数是 x 和 y 坐标,后两个参数是矩形的宽度和高度。 左上角的矩形从其父节点的x = 25y = 25开始。

  1. Line line = new Line(90, 40, 230, 40);
  2. line.setStroke(Color.BLACK);
  3. Circle circle = new Circle(130, 130, 30);
  4. circle.setFill(Color.CHOCOLATE);

LineCircle形状在其构造器中采用绝对坐标值。 线的颜色通过setStroke()方法更改,圆内部的颜色通过setFill()方法更改。

  1. root.getChildren().addAll(rect, line, circle);

所有这三个形状都添加到根节点。

JavaFX 布局窗格 - 图1

图:绝对定位

FlowPane

FlowPane将节点放置在行或列中,当所有节点都无法显示时,将其包裹起来。 流窗格的默认方向为水平。 FlowPane的用法非常有限。

FlowPaneEx.java

  1. package com.zetcode;
  2. import javafx.application.Application;
  3. import javafx.geometry.Insets;
  4. import javafx.geometry.Orientation;
  5. import javafx.scene.Scene;
  6. import javafx.scene.control.Button;
  7. import javafx.scene.layout.FlowPane;
  8. import javafx.stage.Stage;
  9. /**
  10. * ZetCode JavaFX tutorial
  11. *
  12. * This program uses a FlowPane to position
  13. * twenty buttons.
  14. *
  15. * Author: Jan Bodnar
  16. * Website: zetcode.com
  17. * Last modified: June 2015
  18. */
  19. public class FlowPaneEx extends Application {
  20. @Override
  21. public void start(Stage stage) {
  22. initUI(stage);
  23. }
  24. private void initUI(Stage stage) {
  25. FlowPane root = new FlowPane(Orientation.HORIZONTAL, 5, 5);
  26. root.setPadding(new Insets(5));
  27. for (int i=1; i<=20; i++) {
  28. root.getChildren().add(new Button(String.valueOf(i)));
  29. }
  30. Scene scene = new Scene(root, 300, 250);
  31. stage.setTitle("FlowPane");
  32. stage.setScene(scene);
  33. stage.show();
  34. }
  35. public static void main(String[] args) {
  36. launch(args);
  37. }
  38. }

在示例中,我们在FlowPane中放置了二十个按钮。 如果无法将所有按钮都显示在一行中,则将它们包装在其他行中。

  1. FlowPane root = new FlowPane(Orientation.HORIZONTAL, 5, 5);

将创建水平FlowPane。 第二个和第三个参数指定窗格中节点之间的水平和垂直间隙。

  1. root.setPadding(new Insets(5));

setPadding()方法在窗格周围设置一些空间。

  1. for (int i=1; i<=20; i++) {
  2. root.getChildren().add(new Button(String.valueOf(i)));
  3. }

二十个按钮将添加到流窗格中。 这些按钮显示整数值。

JavaFX 布局窗格 - 图2

图:FlowPane

HBox

HBox将其子级布置在单个水平行中。 该窗格与其他布局管理器一起使用以创建布局。 它适合于进行基本布局。

RowOfButtonsEx.java

  1. package com.zetcode;
  2. import javafx.application.Application;
  3. import javafx.geometry.Insets;
  4. import javafx.geometry.Pos;
  5. import javafx.scene.Scene;
  6. import javafx.scene.control.Button;
  7. import javafx.scene.layout.HBox;
  8. import javafx.stage.Stage;
  9. /**
  10. * ZetCode JavaFX tutorial
  11. *
  12. * This program shows four buttons in
  13. * a right-aligned, horizontal row with a HBox.
  14. *
  15. * Author: Jan Bodnar
  16. * Website: zetcode.com
  17. * Last modified: June 2015
  18. */
  19. public class RowOfButtonsEx extends Application {
  20. @Override
  21. public void start(Stage stage) {
  22. initUI(stage);
  23. }
  24. private void initUI(Stage stage) {
  25. HBox root = new HBox(5);
  26. root.setPadding(new Insets(10));
  27. root.setAlignment(Pos.BASELINE_RIGHT);
  28. Button prevBtn = new Button("Previous");
  29. Button nextBtn = new Button("Next");
  30. Button cancBtn = new Button("Cancel");
  31. Button helpBtn = new Button("Help");
  32. root.getChildren().addAll(prevBtn, nextBtn, cancBtn, helpBtn);
  33. Scene scene = new Scene(root);
  34. stage.setTitle("Row of buttons");
  35. stage.setScene(scene);
  36. stage.show();
  37. }
  38. public static void main(String[] args) {
  39. launch(args);
  40. }
  41. }

该示例在一行中显示了四个按钮。 该行右对齐。 按钮之间有一些空间。

  1. HBox root = new HBox(5);

HBox窗格以一定的间距创建。

  1. root.setPadding(new Insets(10));

我们在HBox周围创建一些填充

  1. root.setAlignment(Pos.BASELINE_RIGHT);

setAlignment()方法将节点右对齐。

  1. root.getChildren().addAll(prevBtn, nextBtn, cancBtn, helpBtn);

这些按钮将添加到容器中。

JavaFX 布局窗格 - 图3

图:使用HBox创建的一排按钮

BorderPane

BorderPane将子项放在顶部,左侧,右侧,底部和中央位置。 它可以用来创建经典外观的应用布局。

BorderPaneEx.java

  1. package com.zetcode;
  2. import javafx.application.Application;
  3. import javafx.geometry.Pos;
  4. import javafx.scene.Scene;
  5. import javafx.scene.control.Label;
  6. import javafx.scene.layout.BorderPane;
  7. import javafx.stage.Stage;
  8. /**
  9. * ZetCode JavaFX tutorial
  10. *
  11. * This program places five labels into
  12. * the BorderPane's five areas.
  13. *
  14. * Author: Jan Bodnar
  15. * Website: zetcode.com
  16. * Last modified: June 2015
  17. */
  18. class MyLabel extends Label {
  19. public MyLabel(String text) {
  20. super(text);
  21. setAlignment(Pos.BASELINE_CENTER);
  22. }
  23. }
  24. public class BorderPaneEx extends Application {
  25. private BorderPane root;
  26. private final int SIZE = 60;
  27. @Override
  28. public void start(Stage stage) {
  29. initUI(stage);
  30. }
  31. private void initUI(Stage stage) {
  32. root = new BorderPane();
  33. root.setTop(getTopLabel());
  34. root.setBottom(getBottomLabel());
  35. root.setLeft(getLeftLabel());
  36. root.setRight(getRightLabel());
  37. root.setCenter(getCenterLabel());
  38. Scene scene = new Scene(root, 350, 300);
  39. stage.setTitle("BorderPane");
  40. stage.setScene(scene);
  41. stage.show();
  42. }
  43. private Label getTopLabel() {
  44. Label lbl = new MyLabel("Top");
  45. lbl.setPrefHeight(SIZE);
  46. lbl.prefWidthProperty().bind(root.widthProperty());
  47. lbl.setStyle("-fx-border-style: dotted; -fx-border-width: 0 0 1 0;"
  48. + "-fx-border-color: gray; -fx-font-weight: bold");
  49. return lbl;
  50. }
  51. private Label getBottomLabel() {
  52. Label lbl = new MyLabel("Bottom");
  53. lbl.setPrefHeight(SIZE);
  54. lbl.prefWidthProperty().bind(root.widthProperty());
  55. lbl.setStyle("-fx-border-style: dotted; -fx-border-width: 1 0 0 0;"
  56. + "-fx-border-color: gray; -fx-font-weight: bold");
  57. return lbl;
  58. }
  59. private Label getLeftLabel() {
  60. Label lbl = new MyLabel("Left");
  61. lbl.setPrefWidth(SIZE);
  62. lbl.prefHeightProperty().bind(root.heightProperty().subtract(2*SIZE));
  63. lbl.setStyle("-fx-border-style: dotted; -fx-border-width: 0 1 0 0;"
  64. + "-fx-border-color: gray; -fx-font-weight: bold");
  65. return lbl;
  66. }
  67. private Label getRightLabel() {
  68. Label lbl = new MyLabel("Right");
  69. lbl.setPrefWidth(SIZE);
  70. lbl.prefHeightProperty().bind(root.heightProperty().subtract(2*SIZE));
  71. lbl.setStyle("-fx-border-style: dotted; -fx-border-width: 0 0 0 1;"
  72. + "-fx-border-color: gray; -fx-font-weight: bold");
  73. return lbl;
  74. }
  75. private Label getCenterLabel() {
  76. Label lbl = new MyLabel("Center");
  77. lbl.setStyle("-fx-font-weight: bold");
  78. lbl.prefHeightProperty().bind(root.heightProperty().subtract(2*SIZE));
  79. lbl.prefWidthProperty().bind(root.widthProperty().subtract(2*SIZE));
  80. return lbl;
  81. }
  82. public static void main(String[] args) {
  83. launch(args);
  84. }
  85. }

该示例将五个标签放置在五个BorderPane's区域中。

  1. root.setTop(getTopLabel());
  2. root.setBottom(getBottomLabel());
  3. root.setLeft(getLeftLabel());
  4. root.setRight(getRightLabel());
  5. root.setCenter(getCenterLabel());

使用setTop()setBottom()setLeft()setRight()setCenter()方法定位节点。

  1. Label lbl = new MyLabel("Top");
  2. lbl.setPrefHeight(SIZE);

在这里,我们使用setPrefHeight()方法增加顶部标签的首选高度。 优选的高度是最初显示标签的高度。

  1. lbl.prefWidthProperty().bind(root.widthProperty());

BorderPane尊重其子级的首选大小。 如果是标签,则其大小足以显示其文本。 我们将标签的首选width属性绑定到窗格的相应属性。 这样,标签将从窗格的左到右放大。

  1. lbl.setStyle("-fx-border-style: dotted; -fx-border-width: 0 0 1 0;"
  2. + "-fx-border-color: gray; -fx-font-weight: bold");

我们更改标签的样式以便清楚地看到其边界。

JavaFX 布局窗格 - 图4

图:BorderPane

AnchorPane

AnchorPane将子节点的边缘锚定到与锚定窗格的边缘偏移的位置。 如果锚定窗格设置了边框或填充,则将从这些插图的内部边缘开始测量偏移。 AnchorPane是一个简单的布局窗格,必须与其他布局窗格一起使用才能创建有意义的布局。

CornerButtonsEx.java

  1. package com.zetcode;
  2. import javafx.application.Application;
  3. import javafx.scene.Scene;
  4. import javafx.scene.control.Button;
  5. import javafx.scene.layout.AnchorPane;
  6. import javafx.scene.layout.HBox;
  7. import javafx.stage.Stage;
  8. /**
  9. * ZetCode JavaFX tutorial
  10. *
  11. * This program shows two buttons in the
  12. * bottom-right corner of the window. It uses
  13. * an AnchorPane and an HBox.
  14. *
  15. * Author: Jan Bodnar
  16. * Website: zetcode.com
  17. * Last modified: June 2015
  18. */
  19. public class CornerButtonsEx extends Application {
  20. @Override
  21. public void start(Stage stage) {
  22. initUI(stage);
  23. }
  24. private void initUI(Stage stage) {
  25. AnchorPane root = new AnchorPane();
  26. Button okBtn = new Button("OK");
  27. Button closeBtn = new Button("Close");
  28. HBox hbox = new HBox(5, okBtn, closeBtn);
  29. root.getChildren().addAll(hbox);
  30. AnchorPane.setRightAnchor(hbox, 10d);
  31. AnchorPane.setBottomAnchor(hbox, 10d);
  32. Scene scene = new Scene(root, 300, 200);
  33. stage.setTitle("Corner buttons");
  34. stage.setScene(scene);
  35. stage.show();
  36. }
  37. public static void main(String[] args) {
  38. launch(args);
  39. }
  40. }

该示例使用AnchorPaneHBox将两个按钮放置在窗口的右下角。

  1. AnchorPane root = new AnchorPane();

AnchorPane是场景图的根节点。

  1. Button okBtn = new Button("OK");
  2. Button closeBtn = new Button("Close");
  3. HBox hbox = new HBox(5, okBtn, closeBtn);

这两个按钮位于HBox中。 我们使用一个构造器,将直接放置按钮对象。

  1. root.getChildren().addAll(hbox);

hbox已添加到锚定窗格。

  1. AnchorPane.setRightAnchor(hbox, 10d);

setRightAnchor()方法将hbox锚定到窗格的右边缘。 第二个参数给出了相对于边缘的一些偏移。

  1. AnchorPane.setBottomAnchor(hbox, 10d);

setBottomAnchor()方法将hbox锚定到窗格的底部边缘。

JavaFX 布局窗格 - 图5

图:角按钮

GridPane

GridPane将其节点放入行和列的网格中。 节点可以跨越多行或多列。 GridPane是最灵活的内置布局窗格。

setGridLinesVisible()可以显示布局网格的线条,这使我们可以直观地调试布局。

NewFolderEx.java

  1. package com.zetcode;
  2. import javafx.application.Application;
  3. import javafx.geometry.HPos;
  4. import javafx.geometry.Insets;
  5. import javafx.scene.Scene;
  6. import javafx.scene.control.Button;
  7. import javafx.scene.control.Label;
  8. import javafx.scene.control.ListView;
  9. import javafx.scene.control.TextField;
  10. import javafx.scene.layout.ColumnConstraints;
  11. import javafx.scene.layout.GridPane;
  12. import javafx.scene.layout.Priority;
  13. import javafx.scene.layout.RowConstraints;
  14. import javafx.stage.Stage;
  15. /**
  16. * ZetCode JavaFX tutorial
  17. *
  18. * This program creates a NewFolder layout with
  19. * a GridPane.
  20. *
  21. * Author: Jan Bodnar
  22. * Website: zetcode.com
  23. * Last modified: June 2015
  24. */
  25. public class NewFolderEx extends Application {
  26. @Override
  27. public void start(Stage stage) {
  28. initUI(stage);
  29. }
  30. private void initUI(Stage stage) {
  31. GridPane root = new GridPane();
  32. root.setHgap(8);
  33. root.setVgap(8);
  34. root.setPadding(new Insets(5));
  35. ColumnConstraints cons1 = new ColumnConstraints();
  36. cons1.setHgrow(Priority.NEVER);
  37. root.getColumnConstraints().add(cons1);
  38. ColumnConstraints cons2 = new ColumnConstraints();
  39. cons2.setHgrow(Priority.ALWAYS);
  40. root.getColumnConstraints().addAll(cons1, cons2);
  41. RowConstraints rcons1 = new RowConstraints();
  42. rcons1.setVgrow(Priority.NEVER);
  43. RowConstraints rcons2 = new RowConstraints();
  44. rcons2.setVgrow(Priority.ALWAYS);
  45. root.getRowConstraints().addAll(rcons1, rcons2);
  46. Label lbl = new Label("Name:");
  47. TextField field = new TextField();
  48. ListView view = new ListView();
  49. Button okBtn = new Button("OK");
  50. Button closeBtn = new Button("Close");
  51. GridPane.setHalignment(okBtn, HPos.RIGHT);
  52. root.add(lbl, 0, 0);
  53. root.add(field, 1, 0, 3, 1);
  54. root.add(view, 0, 1, 4, 2);
  55. root.add(okBtn, 2, 3);
  56. root.add(closeBtn, 3, 3);
  57. Scene scene = new Scene(root, 280, 300);
  58. stage.setTitle("New folder");
  59. stage.setScene(scene);
  60. stage.show();
  61. }
  62. public static void main(String[] args) {
  63. launch(args);
  64. }
  65. }

此示例的布局由标签,文本字段,列表视图和两个按钮组成。

  1. GridPane root = new GridPane();

创建GridPane的实例。

  1. root.setHgap(8);
  2. root.setVgap(8);

这两种方法在节点之间创建了水平和垂直间隙。

  1. ColumnConstraints cons1 = new ColumnConstraints();
  2. cons1.setHgrow(Priority.NEVER);
  3. root.getColumnConstraints().add(cons1);
  4. ColumnConstraints cons2 = new ColumnConstraints();
  5. cons2.setHgrow(Priority.ALWAYS);
  6. root.getColumnConstraints().addAll(cons1, cons2);

在布局中,我们需要使第二列可扩展。 默认情况下,网格窗格以其首选大小显示其子级,并且在窗口放大时不会放大它们。 我们创建列约束,将第二列的水平增长优先级设置为Priority.ALWAYS。 (没有特定的方法可以执行此操作。)最后,这会使文本字段和列表视图控件随着窗口的放大而沿水平方向增长。

  1. RowConstraints rcons1 = new RowConstraints();
  2. rcons1.setVgrow(Priority.NEVER);
  3. RowConstraints rcons2 = new RowConstraints();
  4. rcons2.setVgrow(Priority.ALWAYS);
  5. root.getRowConstraints().addAll(rcons1, rcons2);

以类似的方式,使第二行可增长。 通过使第二列和第二行可增长,列表视图将在两个方向上都增长,从而占用了大部分客户区。

  1. Label lbl = new Label("Name:");
  2. TextField field = new TextField();
  3. ListView view = new ListView();
  4. Button okBtn = new Button("OK");
  5. Button closeBtn = new Button("Close");

将创建五个控件。

  1. GridPane.setHalignment(okBtn, HPos.RIGHT);

setHalignment()方法使okBtn右对齐。

  1. root.add(lbl, 0, 0);

标签控件将添加到网格。 add()方法的前两个参数是列和行索引。 索引从零开始。

  1. root.add(field, 1, 0, 3, 1);

重载的add()方法还指定列和行跨度。 文本字段转到第二列和第一行。 它跨越三列和一行。

JavaFX 布局窗格 - 图6

图:新文件夹

MigPane

MigPane是一个非常强大的第三方布局管理器。 它使用MigLayout管理器,可用于 Swing,SWT 和 JavaFX。 强烈建议考虑这位管理器。

JavaFX 布局窗格 - 图7

图:MigPane JAR

要使用MigPane,必须将 JAR 包含到项目库中。 用于源代码和 javadoc 的 JAR 是可选的。

MigPane使用字符串约束进行布局。 有四种约束:常规约束,列约束,行约束和控制约束。 MigPane中有几种布局模式。 网格模式是默认模式,并且是可用模式中最灵活的一种。

MigLayoutWindowsEx.java

  1. package com.zetcode;
  2. import javafx.application.Application;
  3. import javafx.scene.Scene;
  4. import javafx.scene.control.Button;
  5. import javafx.scene.control.Control;
  6. import javafx.scene.control.Label;
  7. import javafx.scene.control.ListView;
  8. import javafx.stage.Stage;
  9. import org.tbee.javafx.scene.layout.MigPane;
  10. /**
  11. * ZetCode JavaFX tutorial
  12. *
  13. * This program creates a Windows layout with
  14. * a MigPane.
  15. *
  16. * Author: Jan Bodnar
  17. * Website: zetcode.com
  18. * Last modified: June 2015
  19. */
  20. public class MigLayoutWindowsEx extends Application {
  21. MigPane root;
  22. @Override
  23. public void start(Stage stage) {
  24. initUI(stage);
  25. }
  26. private void initUI(Stage stage) {
  27. root = new MigPane("", "[grow][]", "[][][grow][]");
  28. Scene scene = new Scene(root);
  29. Label lbl = new Label("Windows");
  30. Button actBtn = new Button("Activate");
  31. Button closeBtn = new Button("Close");
  32. Button okBtn = new Button("OK");
  33. Button helpBtn = new Button("Help");
  34. ListView listView = new ListView();
  35. createLayout(lbl, listView, actBtn, closeBtn, helpBtn, okBtn);
  36. stage.setTitle("Windows");
  37. stage.setScene(scene);
  38. stage.show();
  39. }
  40. private void createLayout(Control...arg) {
  41. root.add(arg[0], "wrap");
  42. root.add(arg[1], "w 200, h 200, span 2 2, grow");
  43. root.add(arg[2], "wrap");
  44. root.add(arg[3], "top, wrap");
  45. root.add(arg[4]);
  46. root.add(arg[5], "skip");
  47. }
  48. public static void main(String[] args) {
  49. launch(args);
  50. }
  51. }

该示例使用六个控件,四个按钮,一个标签和一个列表视图。

  1. root = new MigPane("", "[grow][]", "[][][grow][]");

MigPane构造器的三个字符串指定常规约束,列约束和行约束。 [grow][]约束指定有两列,第一列是可增长的。 同样,[][][grow][]约束告诉MigPane有四行,第三行是可增长的。 如果将debug约束放入常规约束中,则可以直观地调试布局。

  1. createLayout(lbl, listView, actBtn, closeBtn, helpBtn, okBtn);

布局的创建委托给createLayout()方法。

  1. root.add(arg[0], "wrap");

标签控件进入第一行和第一列。 可以(但不是必需)明确指定单元格索引。 wrap约束开始一个新行。

  1. root.add(arg[1], "w 200, h 200, span 2 2, grow");

wh约束指定列表视图控件的初始宽度和高度。 最佳实践是,只有布局管理器才能设置其组件的大小。 换句话说,直接在控件上调用方法行setMinSize()是一种不好的做法。 span约束使控件跨越两列和两行。 最后,grow约束使控件在调整窗口大小时向两个方向扩展。

  1. root.add(arg[2], "wrap");

第三个控件是“激活”按钮。 它在列表视图旁边。 放置此控件后,我们开始新的一行。

  1. root.add(arg[3], "top, wrap");

“关闭”按钮在列表视图旁边,在“激活”按钮下面。 top约束将按钮对齐到其单元格的顶部。

  1. root.add(arg[4]);

我们使列表视图跨两行。 将前一个按钮放入两行后,下一个按钮会自动进入列表视图下方。

  1. root.add(arg[5], "skip");

最后一个按钮跳过一列。 因此它被放置在第三列和第四行。

JavaFX 布局窗格 - 图8

图:窗口 layout created with a MigPane

在 JavaFX 教程的这一部分中,我们提到了布局窗格。