本教程将主要讲JavaFX的GUIs布局控件的应用,以便构建更美观合宜的用户应用界面。
友情提醒:
如果不能看到相应的图片(CSDN直接贴文档里的图片一直不能显示),请下载PDF版“JavaFX2.x专题教程-布局面板”。
在JavaFX应用中,通过设置每个UI元素的位置和尺寸属性,可以实现手动UI控件布局。但是,JavaFX也提供了一个更容易界面布局选择,即利用内置的布局面板。JavaFX的SDK提供了好几个布局容器(谓之面板)来简洁的设置和管理布局,诸如行式、列式、栈式、标题式以及其它等。当视窗尺寸改变时,布局面板自动重定位和改变所包含的节点尺寸,以便保持相关节点属性的一致性。
这个专题中,将对JavaFX布局包内的每个布局面板进行概要介绍并提供相应简单示例。LayoutSample.java文件包含了内置控件主体,源码参见附件1:布局示例。也可下载相应的完整的Netbeans的工程文件:LayoutSample.zip。
下面介绍内置布局面板控件。
BorderPane布局面板内提供了上、下、左、右、中五个区域放置节点,图1-1展示了边界面板的情形。如果实际应用不需要某一区域,可以不需要定义之并不为之分配空间即可。
图1-1 边界面板示例 |
边界面板对于顶部工具栏、底部状态栏、左边导航栏、右边附件信息以及中部工作区的典型外观是非常有用的。
如果窗口比每个区域内容需要的空间大,缺省情况下,多余的将留给中间区域;如果窗口小于需要的空间,则区域就肯能重叠。重叠方式有区域内设置的顺序方式决定。比如,区域设置的顺序为左、底和右,那么当窗口小了,底部将重叠在左边区域,右边将重叠底部区域。如果顺序是左、右和底,那么当窗口小时,底部重叠在左右区域上。
示例1-1展示了边界面板的创建,并用于布局示例应用控件的设置。每个区域应用的创建布局面板的方法,在此主题剩余部分将逐一进行描述。
示例 1-1创建边界面板 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());
|
注意,底部区域在此示例的边界面板中没有用。如果需要增加些内容到底部区域,使用如下语句,并用你选择的控件来代替node内容。
HBox布局面板为在单行中布置一系列节点提供了一种简易方式。如图1-2所示,展示了一个HBox面板示例图。
图1-2 HBox面板 |
特性padding用于设置并管理节点和HBox边缘间的距离。设置特性Spacing间隔用于管理节点间的间距。背景色能通过设置式样风格来改变。示例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("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 边界面板中HBox |
VBox面板是在单列中布置节点对象的,其它与HBox面板类似。图1-4展示了VBox的一个应用示例情况。
图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("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所示。
图1-5 边界面板中VBox应用 |
StackPane布局面板在单一堆栈中放置所有节点,且每个新节点被添加到前一个节点之上。这种布局模式,为在图形或图片上叠加文字或通过叠加普通图形创建复杂图形提供了简易的实现方式。图1-6展示了一个渐变背景的矩形上,通过堆栈方式创建了一个帮助图标。
图1-6 堆栈面板 |
特性alignment用于设置管理面板内子对象如何定位。这个特性应用所有子对象,而margins可设置调整个别子对象在堆栈中的位置。
示例1-4展示了帮助图标的应用堆栈面板情形。
示例 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 to HBox from Example 1-2 HBox.setHgrow(stack, Priority.ALWAYS); // Give stack any extra space }
|
示例1-4代码最后几行把堆栈面板添加到示例1-2的HBox面板中,并且一直放置在面板最右边。结果如图1-7所示。
图1-7 HBox中的堆栈面板 |
GridPane布局面板能创建一种灵活的行列式网格,并可在其中放置节点对象。节点对象可以放置在网格中的任意单元格,并可按需跨越单元格。网格面板对于创建表单或在行列任意组织布局非常有用。图1-8展示了一个网格面板应用情况,包括图标、标题、子标题、文本和饼图等。在此图中,gridLinesVisible属性用于设置网格线,用于展示行、列、以及行列间的间隙。此属性对于调试网格面板布局很有用。
图1-8 网格面板示例 |
Gap特性用于设置管理行列间隔;padding特性用于设置管理节点和网格面板间的的距离。Vertical和horizon对齐特性用于设置管理相应单元格中单个控件的对齐方式。
示例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)); // 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内的节点对象连续的布设,并包装在一定的面板边界集合内。节点可以垂直或水平流水式布设。垂直流面板包装在一定高度的面板内,水平流面板包装在一定宽度的流面板内。图1-10展示了一个使用数字图标的水平流面板。根据约定,垂直流面板内,第一列包含1-4页,第二列包含5-8页。
图1-10 水平流面板示例 |
特性gap用于设置管理行列间间隔;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把所有节点对象放置一个网格内,网格内的单元格或片的尺寸相同。节点以水平行的方式或垂直列的方式布设。水平片以片面板宽度来包装片,垂直片以高为界来包装。用prefColumn和prefRows属性来建立片面板的优先尺寸。Gap特性用于设置管理行列间隔。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布局面板可锚定节点于面板的顶、底、左边、右边或中间。当窗口尺寸调整时,相应节点维护它们相对于锚点的位置。节点可被锚定于多个位置,多个节点也可锚定于同一个位置。图1-12展示了带有锚定顶部的网格面板的锚面板,以及带有两个按钮锚定于底部和右边的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-13 边界面板中锚面板应用 |
随着窗口调整,节点奖维护自己与锚点一直的位置。图1-14展示了随窗口的变小,锚定于底部的按钮如何移动到更靠近销售信息的位置
图1-14 调整锚面板 |
下一篇将专题介绍“事件处理”相关内容。