文档



JavaFX:在JavaFX中使用布局

1 使用内置布局面板

本主题介绍了JavaFX SDK提供的布局容器类,称为面板,用于轻松管理JavaFX应用程序的用户界面。

JavaFX应用程序可以通过设置每个UI元素的位置和大小属性来手动布局UI。然而,更简单的方法是利用布局面板。JavaFX SDK提供了几个布局面板,用于轻松设置和管理经典布局,如行、列、堆栈、平铺等。当窗口调整大小时,布局面板会根据节点的属性自动重新定位和调整节点的大小。

本主题提供了JavaFX布局包提供的每个布局面板的概述和简单示例。文件LayoutSample.java包含了本主题中构建的UI的源代码。文件LayoutSample.zip包含了示例应用程序的NetBeans IDE项目。

BorderPane

BorderPane布局面板提供了五个区域来放置节点:顶部、底部、左侧、右侧和中心。 图1-1展示了使用边界面板可以创建的布局类型。这些区域可以是任意大小。如果你的应用程序不需要其中的某个区域,你不需要定义它,也不会为其分配空间。

图1-1 示例边界面板

图1-1的描述
"图1-1 示例边界面板"的描述

边界面板适用于经典的界面布局,例如顶部的工具栏、底部的状态栏、左侧的导航面板、右侧的附加信息和中心的工作区域。

如果窗口比每个区域内容所需的空间大,多余的空间默认分配给中心区域。如果窗口比每个区域内容所需的空间小,区域可能会重叠。重叠的顺序由区域设置的顺序决定。例如,如果区域的顺序是左侧、底部和右侧,当窗口变小时,底部区域会重叠左侧区域,右侧区域会重叠底部区域。如果顺序是左侧、右侧和底部,当窗口变小时,底部区域会同时重叠左侧和右侧区域。

示例1-1展示了创建边界面板的代码,该面板用于布局示例应用程序构建的用户界面。在本主题的其余部分中,将介绍用于创建每个区域中使用的布局面板的方法。

示例1-1 创建边界面板

BorderPane border = new BorderPane();
HBox hbox = addHBox()
border.setTop(hbox);
border.setLeft(addVBox());
addStackPane(hbox);         // 将堆栈添加到顶部区域的HBox中

border.setCenter(addGridPane());
border.setRight(addFlowPane());

请注意,此示例中未使用边界面板的底部区域。如果你想向底部区域添加内容,请使用以下语句,并将node替换为你选择的控件:

border.setBottom(node);

HBox

HBox布局面板提供了一种简单的方式来将一系列节点排列在一行中。 图1-2显示了一个HBox面板的示例。

图1-2 示例HBox面板

图1-2的描述如下
"图1-2 示例HBox面板"的描述

可以设置padding属性来管理节点与HBox面板边缘之间的距离。可以设置spacing来管理节点之间的距离。可以设置style来改变背景颜色。

示例1-2创建了一个包含两个按钮的工具栏的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("当前");
    buttonCurrent.setPrefSize(100, 20);

    Button buttonProjected = new Button("预测");
    buttonProjected.setPrefSize(100, 20);
    hbox.getChildren().addAll(buttonCurrent, buttonProjected);

    return hbox;
}

示例1-1中的setTop()方法将HBox面板添加到边界面板的顶部区域。结果如图1-3所示。

图1-3 边界面板中的HBox面板

图1-3的描述如下
"图1-3 边界面板中的HBox面板"的描述

VBox

VBox布局面板与HBox布局面板类似,只是节点按照单列排列。示例VBox面板如图1-4所示。

图1-4 示例VBox面板

图1-4的描述
图1-4 示例VBox面板的描述

可以通过设置padding属性来管理节点与VBox面板边缘之间的距离。可以通过设置spacing来管理节点之间的距离。可以通过设置margins来在各个控件周围添加额外的空间。

示例1-3创建了一个用于选项列表的VBox面板。

示例1-3 创建VBox面板

public VBox addVBox(); {
    VBox vbox = new VBox();
    vbox.setPadding(new Insets(10));
    vbox.setSpacing(8);

    Text title = new Text("数据");
    title.setFont(Font.font("Arial", FontWeight.BOLD, 14));
    vbox.getChildren().add(title);

    Hyperlink options[] = new Hyperlink[] {
        new Hyperlink("销售"),
        new Hyperlink("市场营销"),
        new Hyperlink("分销"),
        new Hyperlink("成本")};

    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所示。

图1-5 边界面板中的VBox面板

图1-5的描述
图1-5 边界面板中的VBox面板的描述

StackPane

StackPane布局容器将所有节点放置在一个堆栈中,每个新节点都会叠加在前一个节点之上。这种布局模型提供了一种简单的方式,可以在形状或图像上叠加文本,或者重叠常见的形状以创建复杂的形状。图1-6显示了一个帮助图标,它是通过将一个问号叠加在具有渐变背景的矩形上创建的。

图1-6 示例Stack Pane

图1-6的描述如下
图1-6的描述

可以设置对齐属性来管理在堆栈面板中的子节点的位置。该属性影响所有子节点,因此可以设置边距来调整堆栈中各个子节点的位置。

示例1-4创建了一个用于帮助图标的堆栈面板。

示例1-4 创建Stack Pane

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);     // 右对齐堆栈中的节点
    StackPane.setMargin(helpText, new Insets(0, 10, 0, 0)); // 居中显示"?"

    hb.getChildren().add(stack);            // 将堆栈面板添加到HBox对象
    HBox.setHgrow(stack, Priority.ALWAYS);    // 给堆栈面板分配任何额外的空间
}

示例1-4中的最后几行代码将堆栈面板添加到示例1-2中创建的HBox面板,并将其定位在面板的最右边。结果如图1-7所示。

图1-7 HBox面板中的Stack Pane

图1-7的描述如下
图1-7的描述

GridPane

GridPane布局面板使您能够创建一个灵活的行列网格,用于布局节点。节点可以放置在网格的任何单元格中,并根据需要跨越单元格。网格面板适用于创建表单或任何以行列组织的布局。 图1-8显示了一个包含图标、标题、副标题、文本和饼图的网格面板。在此图中,gridLinesVisible属性设置为显示网格线,显示行、列和行列之间的间隙。此属性对于可视化调试GridPane布局非常有用。

图1-8 示例网格面板

图1-8的描述如下
"图1-8 示例网格面板"的描述

可以设置间隙属性来管理行和列之间的间距。可以设置填充属性来管理节点与网格面板边缘之间的距离。可以设置垂直和水平对齐属性来管理单元格中各个控件的对齐方式。

示例1-5创建了图1-8中显示的网格面板。

示例1-5 创建网格面板

public GridPane addGridPane() {
    GridPane grid = new GridPane();
    grid.setHgap(10);
    grid.setVgap(10);
    grid.setPadding(new Insets(0, 10, 0, 10));

    // 第2列,第1行的类别
    Text category = new Text("销售:");
    category.setFont(Font.font("Arial", FontWeight.BOLD, 20));
    grid.add(category, 1, 0); 

    // 第3列,第1行的标题
    Text chartTitle = new Text("本年度");
    chartTitle.setFont(Font.font("Arial", FontWeight.BOLD, 20));
    grid.add(chartTitle, 2, 0);

    // 第2-3列,第2行的副标题
    Text chartSubtitle = new Text("商品和服务");
    grid.add(chartSubtitle, 1, 1, 2, 1);

    // 第1列,第1-2行的房子图标
    ImageView imageHouse = new ImageView(
      new Image(LayoutSample.class.getResourceAsStream("graphics/house.png")));
    grid.add(imageHouse, 0, 0, 1, 2); 

    // 第1列(底部),第3行的左侧标签
    Text goodsPercent = new Text("商品\n80%");
    GridPane.setValignment(goodsPercent, VPos.BOTTOM);
    grid.add(goodsPercent, 0, 2); 

    // 第2-3列,第3行的图表
    ImageView imageChart = new ImageView(
     new Image(LayoutSample.class.getResourceAsStream("graphics/piechart.png")));
    grid.add(imageChart, 1, 2, 2, 1); 

    // 第4列(顶部),第3行的右侧标签
    Text servicesPercent = new Text("服务\n20%");
    GridPane.setValignment(servicesPercent, VPos.TOP);
    grid.add(servicesPercent, 3, 2);

    return grid;
}

setCenter()方法在示例1-1中将网格面板添加到边界面板的中心区域。结果如图1-9所示。

图1-9 边界面板中的网格面板

图1-9的描述如下
"图1-9 边界面板中的网格面板"的描述

当窗口大小调整时,网格面板中的节点根据其布局约束进行调整大小。

FlowPane

FlowPane布局面板中的节点按顺序布局,并在面板设置的边界处换行。节点可以垂直流动(按列)或水平流动(按行)。垂直流动面板在面板的高度边界处换行。水平流动面板在面板的宽度边界处换行。 图1-10显示了一个使用编号图标的水平流动面板示例。相比之下,在垂直流动面板中,第一列将包含第1至第4页,第二列将包含第5至第8页。

图1-10 示例水平流动面板

图1-10的描述
"图1-10 示例水平流动面板"的描述

可以设置间隔属性来管理行和列之间的间距。可以设置填充属性来管理节点与面板边缘之间的距离。 示例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 边界面板中的流动面板

图1-11的描述
"图1-11 边界面板中的流动面板"的描述

TilePane

TilePane(瓷砖面板)类似于FlowPane(流式面板)。TilePane布局面板将所有节点放置在一个网格中,每个单元格或瓷砖的大小相同。节点可以水平排列(按行)或垂直排列(按列)。水平排列在瓷砖面板的宽度边界处换行,垂直排列在高度边界处换行。使用prefColumnsprefRows属性来确定瓷砖面板的首选大小。

可以设置间隔属性来管理行和列之间的间距。可以设置填充属性来管理节点与面板边缘之间的距离。

示例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-12的描述
图1-12的描述

示例1-8创建了一个锚点面板,其中一个节点锚定到面板的顶部,另一个节点锚定到面板的右下角。在示例1-8中使用了示例1-5中创建的网格。

示例1-8 创建一个锚点面板

public AnchorPane addAnchorPane(GridPane grid) {
    AnchorPane anchorpane = new AnchorPane();
    Button buttonSave = new Button("保存");
    Button buttonCancel = new Button("取消");

    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);   // 添加示例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-13 边界面板中的锚点面板

图1-13的描述
图1-13的描述

当窗口调整大小时,节点根据其锚点在面板中保持位置不变。如图1-14所示,按钮被锚定在面板底部,随着窗口变小,它们靠近销售信息。

图1-14 调整大小的锚定面板

图1-14的描述如下
"图1-14 调整大小的锚定面板"的描述

其他资源

要了解更多关于JavaFX中的布局面板的信息,请参阅javafx.scene.layout包在JavaFX API文档中的信息。

应用程序文件

源代码 

NetBeans项目 

关闭窗口

目录

JavaFX:在JavaFX中使用布局

展开 折叠