内建布局使用
本主题描述JavaFX SDK随附的布局容器类(称为窗格)。 使用布局窗格可以轻松管理JavaFX应用程序的用户界面。
JavaFX应用程序可以通过设置每个UI元素的position和size属性来手动布置UI。 但是,一个更简单的选择是使用布局窗格。 JavaFX SDK提供了几个布局窗格,用于轻松设置和管理经典布局,例如行,列,堆栈,图块等。 调整窗口大小时,布局窗格会根据节点的属性自动调整其位置和大小。
BorderPane
BorderPane布局窗格提供五个可放置节点的区域:顶部,底部,左侧,右侧和中心。 图1-1显示了可以使用边框窗格创建的布局类型。 区域可以是任何大小。 如果您的应用程序不需要区域之一,则无需定义它,也不会为其分配任何空间。
图1-1
边框窗格对于顶部的工具栏,底部的状态栏,左侧的导航面板,右侧的附加信息以及中央的工作区域的经典外观很有用。
如果窗口大于每个区域的内容所需的空间,则默认情况下会将多余的空间分配给中心区域。如果窗口小于每个区域的内容所需的空间,则这些区域可能会重叠。重叠由区域设置的顺序确定。例如,如果以左,下和右的顺序设置区域,则当窗口变小时,底部区域与左侧区域重叠,而右侧区域与底部区域重叠。如果按左,右和底部的顺序设置,则当窗口变小时,底部区域将与左侧和右侧区域重叠。
例1-1显示了用于创建边框窗格的代码,该边框窗格用于由Layout Sample应用程序构建的UI。本主题的其余部分介绍了创建每个区域中使用的布局窗格的方法。
BorderPane border = new BorderPane();
HBox hbox = addHBox()
border.setTop(hbox);
border.setLeft(addVBox());
addStackPane(hbox); // Add stack to HBox in top region
border.setCenter(addGridPane());
border.setRight(addFlowPane());
HBox
HBox布局窗格提供了一种在一行中排列一系列节点的简便方法。 图1-2显示了HBox窗格的示例。
图1-2
可以设置padding属性来管理节点与HBox窗格的边缘之间的距离。 可以设置间距来管理节点之间的距离。 可以设置样式以更改背景颜色。
示例1-2创建HBox窗格
public HBox addHBox() {
HBox hbox = new HBox();
hbox.setPadding(new Insets(15, 12, 15, 12));
hbox.setSpacing(10);
hbox.setStyle("-fx-background-color: #336699;");
Button buttonCurrent = new Button("Current");
buttonCurrent.setPrefSize(100, 20);
Button buttonProjected = new Button("Projected");
buttonProjected.setPrefSize(100, 20);
hbox.getChildren().addAll(buttonCurrent, buttonProjected);
return hbox;
}
示例1-1中的setTop()方法将HBox窗格添加到边框窗格的顶部区域。 结果如图1-3所示。
图1-3
VBox
VBox布局窗格类似于HBox布局窗格,不同之处在于节点排列在单个列中。 图1-4显示了VBox窗格的示例。
图1-4示例VBox窗格
可以设置padding属性来管理节点与VBox窗格的边缘之间的距离。 可以设置间距来管理节点之间的距离。 可以设置边距以在单个控件周围添加额外的空间。
示例1-3创建一个VBox窗格
public VBox addVBox(); {
VBox vbox = new VBox();
vbox.setPadding(new Insets(10));
vbox.setSpacing(8);
Text title = new Text("Data");
title.setFont(Font.font("Arial", FontWeight.BOLD, 14));
vbox.getChildren().add(title);
Hyperlink options[] = new Hyperlink[] {
new Hyperlink("Sales"),
new Hyperlink("Marketing"),
new Hyperlink("Distribution"),
new Hyperlink("Costs")};
for (int i=0; i<4; i++) {
VBox.setMargin(options[i], new Insets(0, 0, 0, 8));
vbox.getChildren().add(options[i]);
}
return vbox;
}
示例1-1中的setLeft()方法将VBox窗格添加到边框窗格的左侧区域。 结果如图1-5所示。
StackPane
StackPane布局窗格将所有节点放在单个堆栈中,而每个新节点都添加在前一个节点的顶部。 此布局模型提供了一种简单的方法来将文本覆盖在形状或图像上,或将常见的形状重叠以创建复杂的形状。 图1-6显示了一个帮助图标,该图标是通过在带有渐变背景的矩形上方堆叠一个问号而创建的。
图1-6样品堆栈窗格
可以设置alignment属性来管理子元素在堆栈窗格中的放置方式。 此属性影响所有子项,因此可以设置边距来调整单个子项在堆栈中的位置。
示例1-4创建堆栈窗格
public void addStackPane(HBox hb) {
StackPane stack = new StackPane();
Rectangle helpIcon = new Rectangle(30.0, 25.0);
helpIcon.setFill(new LinearGradient(0,0,0,1, true, CycleMethod.NO_CYCLE,
new Stop[]{
new Stop(0,Color.web("#4977A3")),
new Stop(0.5, Color.web("#B0C6DA")),
new Stop(1,Color.web("#9CB6CF")),}));
helpIcon.setStroke(Color.web("#D0E6FA"));
helpIcon.setArcHeight(3.5);
helpIcon.setArcWidth(3.5);
Text helpText = new Text("?");
helpText.setFont(Font.font("Verdana", FontWeight.BOLD, 18));
helpText.setFill(Color.WHITE);
helpText.setStroke(Color.web("#7080A0"));
stack.getChildren().addAll(helpIcon, helpText);
stack.setAlignment(Pos.CENTER_RIGHT); // Right-justify nodes in stack
StackPane.setMargin(helpText, new Insets(0, 10, 0, 0)); // Center "?"
hb.getChildren().add(stack); // Add stack pane to HBox object
HBox.setHgrow(stack, Priority.ALWAYS); // Give stack any extra space
}
例1-4中的最后几行代码将堆栈窗格添加到例1-2中创建的HBox窗格中,并将其始终置于窗格的最右边。 结果如图1-7所示。
图1-7 HBox窗格中的堆栈窗格
GridPane
GridPane布局窗格使您可以创建行和列的灵活网格,以在其中布置节点。 节点可以放置在网格中的任何单元中,并且可以根据需要跨越单元。 网格窗格可用于创建以行和列组织的表单或任何布局。 图1-8显示了一个网格窗格,其中包含图标,标题,副标题,文本和饼图。 在此图中,gridLinesVisible属性设置为显示网格线,这些网格线显示行和列以及行和列之间的间隙。 此属性对于以可视方式调试GridPane布局很有用。
图1-8示例网格窗格
可以设置间隙属性来管理行和列之间的间距。 可以设置padding属性来管理节点与网格窗格边缘之间的距离。 可以设置垂直和水平对齐属性以管理单元格中各个控件的对齐。
例1-5创建了如图1-8所示的网格窗格。
public GridPane addGridPane() {
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(0, 10, 0, 10));
// Category in column 2, row 1
Text category = new Text("Sales:");
category.setFont(Font.font("Arial", FontWeight.BOLD, 20));
grid.add(category, 1, 0);
// Title in column 3, row 1
Text chartTitle = new Text("Current Year");
chartTitle.setFont(Font.font("Arial", FontWeight.BOLD, 20));
grid.add(chartTitle, 2, 0);
// Subtitle in columns 2-3, row 2
Text chartSubtitle = new Text("Goods and Services");
grid.add(chartSubtitle, 1, 1, 2, 1);
// House icon in column 1, rows 1-2
ImageView imageHouse = new ImageView(
new Image(LayoutSample.class.getResourceAsStream("graphics/house.png")));
grid.add(imageHouse, 0, 0, 1, 2);
// Left label in column 1 (bottom), row 3
Text goodsPercent = new Text("Goods\n80%");
GridPane.setValignment(goodsPercent, VPos.BOTTOM);
grid.add(goodsPercent, 0, 2);
// Chart in columns 2-3, row 3
ImageView imageChart = new ImageView(
new Image(LayoutSample.class.getResourceAsStream("graphics/piechart.png")));
grid.add(imageChart, 1, 2, 2, 1);
// Right label in column 4 (top), row 3
Text servicesPercent = new Text("Services\n20%");
GridPane.setValignment(servicesPercent, VPos.TOP);
grid.add(servicesPercent, 3, 2);
return grid;
}
示例1-1中的setCenter()方法将网格窗格添加到边框窗格的中心区域。 结果如图1-9所示。
图1-9边框窗格中的网格窗格
调整窗口大小时,网格窗格内的节点将根据其布局约束进行调整。
FlowPane
FlowPane布局窗格中的节点连续布置,并包装在该窗格的边界集上。 节点可以垂直(按列)或水平(按行)流动。 垂直流动窗格环绕在窗格的高度边界处。 水平流动窗格环绕窗格的宽度边界。 图1-10显示了带有数字图标的示例水平流窗格。 相反,在垂直流窗格中,第一列将包含第一到第四页,第二列将包含第五到第八页。
图1-10示例水平流窗格
可以设置间隙属性来管理行和列之间的间距。 可以设置padding属性来管理节点与窗格边缘之间的距离。 例1-6为一系列页面图标创建了一个水平流程窗格。
示例1-6创建流窗格
public FlowPane addFlowPane() {
FlowPane flow = new FlowPane();
flow.setPadding(new Insets(5, 0, 5, 0));
flow.setVgap(4);
flow.setHgap(4);
flow.setPrefWrapLength(170); // preferred width allows for two columns
flow.setStyle("-fx-background-color: DAE6F3;");
ImageView pages[] = new ImageView[8];
for (int i=0; i<8; i++) {
pages[i] = new ImageView(
new Image(LayoutSample.class.getResourceAsStream(
"graphics/chart_"+(i+1)+".png")));
flow.getChildren().add(pages[i]);
}
return flow;
}
示例1-1中的setRight()方法将流窗格添加到边框窗格的右侧区域。 结果如图1-11所示。
图1-11边框窗格中的流窗格
TilePane
磁贴窗格类似于流窗格。 TilePane布局窗格将所有节点放在一个网格中,每个单元或图块的大小均相同。 节点可以水平(行)或垂直(列)布局。 水平平铺将瓷砖平铺在平铺窗格的宽度边界处,垂直平铺将瓷砖平铺在高度边界处。 使用prefColumns和prefRows属性来确定平铺窗格的首选大小。
可以设置间隙属性来管理行和列之间的间距。 可以设置padding属性来管理节点与窗格边缘之间的距离。
例1-7创建了一个水平瓷砖窗格,该窗格的布局与图1-10所示相同。
示例1-7创建平铺窗格
TilePane tile = new TilePane();
tile.setPadding(new Insets(5, 0, 5, 0));
tile.setVgap(4);
tile.setHgap(4);
tile.setPrefColumns(2);
tile.setStyle("-fx-background-color: DAE6F3;");
ImageView pages[] = new ImageView[8];
for (int i=0; i<8; i++) {
pages[i] = new ImageView(
new Image(LayoutSample.class.getResourceAsStream(
"graphics/chart_"+(i+1)+".png")));
tile.getChildren().add(pages[i]);
}
AnchorPane
AnchorPane布局窗格使您可以将节点锚定到窗格的顶部,底部,左侧,右侧或中心。 调整窗口大小时,节点将保持其相对于锚点的位置。 节点可以锚定到一个以上的位置,多个节点可以锚定到同一位置。 图1-12显示了一个锚定窗格,其中GridPane的网格窗格锚定在顶部,而HBox窗格的底部和右侧锚定了两个按钮。
图1-12示例锚定窗格
示例1-8创建了一个锚定窗格,其中一个节点锚定在该窗格的顶部,而一个节点锚定在该窗格的右下方。 在示例1-5中创建的网格用于顶部节点。
示例1-8创建一个锚定窗格
public AnchorPane addAnchorPane(GridPane grid) {
AnchorPane anchorpane = new AnchorPane();
Button buttonSave = new Button("Save");
Button buttonCancel = new Button("Cancel");
HBox hb = new HBox();
hb.setPadding(new Insets(0, 10, 10, 10));
hb.setSpacing(10);
hb.getChildren().addAll(buttonSave, buttonCancel);
anchorpane.getChildren().addAll(grid,hb); // Add grid from Example 1-5
AnchorPane.setBottomAnchor(hb, 8.0);
AnchorPane.setRightAnchor(hb, 5.0);
AnchorPane.setTopAnchor(grid, 10.0);
return anchorpane;
}
以下语句将锚定窗格替换为边框窗格的中心区域:
border.setCenter(addAnchorPane(addGridPane()));
图1-13边框窗格中的锚定窗格
调整窗口大小时,节点将根据其锚点保持其在窗格中的位置。 图1-14显示了固定在窗格底部的按钮如何随着窗口的变小而更靠近销售信息。
图1-14调整大小的锚定窗格