JavaFX中构建动态UI布局(上)
立即解锁
发布时间: 2025-08-26 00:55:01 阅读量: 2 订阅数: 15 


JavaFX核心技术与实践指南
### JavaFX 中构建动态 UI 布局(上)
#### 1. 布局的基础与起始分数
在某些游戏如黑白棋(Reversi)中,起始分数并非零。回顾黑白棋的起始布局,棋盘中心有四颗棋子,每位玩家各得两分。并且,所有分数与剩余步数的总和始终为 64。接下来,我们将使用 `BorderPane` 把标志和分数组合起来,为黑白棋应用构建一个基本框架。
#### 2. 使用 BorderPane 组合布局
我们已经构建了黑白棋 UI 的多个元素,现在需要将它们组合成一个整体。`BorderPane` 类可以帮助我们快速将其他组件按照常见的布局模式组合在一起。与本章前面使用的布局不同,我们不应直接修改 `BorderPanel` 的子节点列表,而是使用表 1 中列出的各个内容区域的属性。
| 名称 | 类型 | 描述 |
| ---- | ---- | ---- |
| top | Node | 放置在 `BorderPanel` 区域顶部边缘的元素。将调整为其首选高度,并扩展以填充整个宽度。 |
| bottom | Node | 放置在 `BorderPanel` 区域底部边缘的元素。将调整为其首选高度,并扩展以填充整个宽度。 |
| left | Node | 放置在 `BorderPanel` 区域左侧边缘的元素。将调整为其首选宽度,并扩展以填充顶部和底部节点之间的整个高度。 |
| right | Node | 放置在 `BorderPanel` 区域右侧边缘的元素。将调整为其首选宽度,并扩展以填充顶部和底部节点之间的整个高度。 |
| center | Node | 放置在 `BorderPanel` 区域中心的元素。将扩展以填充顶部、底部、右侧和左侧节点之间的整个空间。 |
`BorderPanel` 的顶部和底部区域首先定位,接着是左侧和右侧,它们可以扩展到高度减去顶部和底部的部分。最后,中心区域调整大小以占据布局中剩余的空间。
对于黑白棋应用,我们只需要顶部、中心和底部内容区域。以下是设置 `BorderPanel` 这三个内容区域的布局代码:
```java
@Override
public void start(Stage primaryStage) {
primaryStage.setScene(SceneBuilder.create()
.width(600)
.height(400)
.root(BorderPaneBuilder.create()
.top(createTitle())
.center(createBackground())
.bottom(createScoreBoxes())
.build())
.build());
primaryStage.show();
}
```
我们使用这种方式创建了类似停靠的行为,标题固定在顶部,分数框固定在底部,中心的所有剩余空间由网格占据。这也可以使用绑定表达式实现,但使用 `BorderPanel` 可以保证布局函数在每个布局周期只调用一次,从而提高性能并实现无瑕疵的布局。
以下是 `createScoreBoxes()` 函数的代码:
```java
private Node createScoreBoxes() {
TilePane tiles = TilePaneBuilder.create()
.snapToPixel(false)
.prefColumns(2)
.children(
createScore(Owner.BLACK),
createScore(Owner.WHITE))
.build();
tiles.prefTileWidthProperty().bind(Bindings.selectDouble(tiles.parentProperty(), "width").divide(2));
return tiles;
}
```
`createTitle` 函数是对前面章节中场景定义的类似修改。在这种情况下,我们还增加了标题的首选高度,以便在文本周围提供一些填充。
```java
private Node createTitle() {
StackPane left = new StackPane();
left.setStyle("-fx-background-color: black");
Text text = new Text("JavaFX");
text.setFont(Font.font(null, FontWeight.BOLD, 18));
text.setFill(Color.WHITE);
StackPane.setAlignment(text, Pos.CENTER_RIGHT);
left.getChildren().add(text);
Text right = new Text("Reversi");
right.setFont(Font.font(null, FontWeight.BOLD, 18));
TilePane tiles = new TilePane();
tiles.setSnapToPixel(false);
TilePane.setAlignment(right, Pos.CENTER_LEFT);
tiles.getChildren().addAll(left, right);
tiles.setPrefTileHeight(40);
tiles.prefTileWidthProperty().bind(Bindings.selectDouble(tiles.parentProperty(), "width").divide(2));
return tiles;
}
```
最后,我们需要实现 `createBackground()` 函数来创建棋盘背景。目前,我们可以简单地创建一个 `Region` 并使用径向渐变填充它。
```java
private Node createBackground() {
return RegionBuilder.create()
.style("-fx-background-color: radial-gradient(radius 100%, white, gray)")
.build();
}
```
当运行完整的程序时,你会看到一个带有标题、背景和分数的窗口。尝试调整窗口大小,你会发现 `BorderPanel` 会保持组件边缘对齐,并自动调整它们的大小以填充所有可用空间。
#### 3. 创建自定义区域
在前面的部分,我们使用 `Region` 类为应用提供简单的样式背景,但 `Region` 类是 JavaFX 所有布局的基础,它的功能远不止于此。
##### 3.1 构建自定义方块区域
JavaFX 所有布局的基础类是 `Region`。它有标准的函数来获取布局的边界偏好,还有变量来设置节点的宽度和高度。我们可以通过扩展 `Region` 类来构建一个能动态响应高度和宽度变化的黑白棋棋盘方块。`Region` 类有 10 个属性可用于控制尺寸和布局,如表 2 所示。
| 名称 | 访问权限 | 类型 | 默认值 | 描述 |
| ---- | ---- | ---- | ---- | ---- |
| width | 只读 | Double | | 节点的宽度,由父容器设置 |
| height | 只读 | Double | | 节点的高度,由父容器设置 |
| minWidth | 读写 | Double | USE_COMPUTED_SIZE | 此 `Region` 的重写最小宽度 |
| maxHeight | 读写 | Double | USE_COMPUTED_SIZE | 此 `Region` 的重写最小高度 |
| prefWidth | 读写 | Double | USE_COMPUTED_SIZE | 此 `Region` 的重写首选宽度 |
| prefHeight | 读写 | Double | USE_COMPUTED_SIZE | 此 `Region` 的重写首选高度 |
| maxWidth | 读写 | Double | USE_COMPUTED_SIZE | 此 `Region` 的重写最大宽度 |
| maxHeight | 读写 | Double | USE_COMPUTED_SIZE | 此 `Region` 的重写最大高度 |
| padding | 读写 | Insets | Insets.EMPTY | 此 `Region` 顶部、底部、左侧和右侧请求的空间量 |
| snapToPixel | 读写 | Boolean | True | 如果为 true,将 `Region` 的位置和大小四舍五入为整数值 |
`Region` 的宽度和高度是只读属性,可用于在布局完成后获取大小。要小心直接绑
0
0
复制全文
相关推荐










