在JavaFX中使用布局.docx
《在JavaFX中使用布局.docx》由会员分享,可在线阅读,更多相关《在JavaFX中使用布局.docx(39页珍藏版)》请在冰豆网上搜索。
在JavaFX中使用布局
在JavaFX中使用布局
一、用内置布局窗格
一个JavaFx应用可以通过设置每个UI元素的位置和大小来手动地布局用户界面。
但是,一个更简单的做法是使用布局窗格。
JavaFxSDK提供了多种布局容器类,叫做窗格,它们可简化对一些经典布局的设置和管理,例如行、列、堆叠、平铺等等。
当窗口缩放时,布局窗格会自动地根据节点属性重设其包含的所有节点的位置和大小。
本话题为JavaFxlayout包中提供的的每个布局窗格都给出了相应的概述和简单的示例。
LayoutSample.java文件包含了本话题中UI的源码。
LayoutSample.zip文件包含了示例应用的NetBeans工程。
BorderPane
BorderPane布局窗格提供了5个放置节点的区域:
top,bottom,left,right,和center。
图1-1展示了borderpane构建的布局样式。
这些区域可以是任意大小,如果应用不需要某个区域,你可以不定义它,然后窗格就不会给这个区域分配空间。
图1-1BorderPane示例
borderpane可用于这种经典的外观:
top:
工具栏,bottom:
状态栏,left:
导航栏,right:
附加信息,center:
工作区。
默认情况下,如果窗口比所有区域所需空间还大,多余的空间将被分配给中间区域。
如果窗口比所需空间小,区域可能会重叠。
重叠是由区域设置的顺序决定的。
例如,如果区域设置的顺序是left,bottom,right,当窗口变得更小时,bottom区域会覆盖left区域,right区域会覆盖bottom区域。
如果区域设置的顺序是left,right,bottom,当窗口变得更小时,bottom区域会覆盖left和right区域。
例1-1 展示了布局示例应用中创建borderpane的代码。
创建每个区域用到的布局窗格的函数会在本话题的剩余部分介绍。
例1-1创建一个BorderPane
1.BorderPaneborder=newBorderPane();
2.HBoxhbox=addHBox()
3.border.setTop(hbox);
4.border.setLeft(addVBox());
5.addStackPane(hbox);//在top区域的HBox中添加stackpane
6.
7.border.setCenter(addGridPane());
8.border.setRight(addFlowPane());
注意一点,在本例中,borderpane的bottom区域并没有被使用。
如果你想要在bottom区域中添加什么,可以使用下面的语句并且替换其中的节点node为你选择的控件。
1.border.setBottom(node);
HBox
HBox 布局窗格可以让你很容易地将一系列节点排列到一行中。
图1-2 展示了一个 HBox 窗格的例子.
图1-2HBox窗格示例
Padding属性可以设置节点到 HBox 边缘的距离。
Spacing可以管理节点之间的距离。
Style可用来改变背景色。
例1-2 为一个工具栏创建了一个包含两个按钮的 HBox 窗格。
例1-2创建一个HBox窗格
1.publicHBoxaddHBox(){
2.HBoxhbox=newHBox();
3.hbox.setPadding(newInsets(15,12,15,12));
4.hbox.setSpacing(10);
5.hbox.setStyle("-fx-background-color:
#336699;");
6.
7.ButtonbuttonCurrent=newButton("Current");
8.buttonCurrent.setPrefSize(100,20);
9.
10.ButtonbuttonProjected=newButton("Projected");
11.buttonProjected.setPrefSize(100,20);
12.hbox.getChildren().addAll(buttonCurrent,buttonProjected);
13.
14.returnhbox;
15.}
例1-1中的 setTop() 函数将这个 HBox 窗格添加到borderpane的top区域。
其结果展示在图1-3中。
图1-3BorderPane中的 HBoxPane
VBox
VBox 布局窗格和 HBox 很相似,除了这里所有节点是被排列到一个列中的。
图1-4 展示了一个 VBox 窗格的示例。
图1-4VBoxPane示例
Padding可用于设置节点到 VBox 窗格边界的距离。
Spacing可管理节点之间的距离。
Margins可在单独的控件周围添加额外的空间。
译者注:
padding又称内边距、补白或留白,margin又称外边距、边界或额外空白区。
它们的概念来源于CSS,即层叠样式表。
从一般意义上讲,margin是用来隔开元素与元素的间距;padding是用来隔开元素与内容的间隔。
margin用于布局分开元素使元素与元素互不相干;padding用于元素与内容之间的间隔,让内容(文字)与(包裹)元素之间有一段“呼吸距离”。
(参考文章)
例1-3 创建了一个包含一列选项的 VBox 窗格。
例1-3创建一个VBoxPane
1.publicVBoxaddVBox();{
2.VBoxvbox=newVBox();
3.vbox.setPadding(newInsets(10));
4.vbox.setSpacing(8);
5.
6.Texttitle=newText("Data");
7.title.setFont(Font.font("Arial",FontWeight.BOLD,14));
8.vbox.getChildren().add(title);
9.
10.Hyperlinkoptions[]=newHyperlink[]{
11.newHyperlink("Sales"),
12.newHyperlink("Marketing"),
13.newHyperlink("Distribution"),
14.newHyperlink("Costs")};
15.
16.for(inti=0;i<4;i++){
17.VBox.setMargin(options[i],newInsets(0,0,0,8));
18.vbox.getChildren().add(options[i]);
19.}
20.
21.returnvbox;
22.}
例1-1 中的 setLeft() 函数将这个 VBox 窗格添加到了borderpane的left区域。
其结果展示在 图1-5 中。
图1-5BorderPane中的VBoxPane
StackPane
StackPane 布局窗格能将所有的节点放到一个堆栈中,其中每一个新的节点被添加到前一个节点的上方。
这个布局模型能让你很容易地在一个形状或图像上面覆盖一个文本,或者用常用形状互相覆盖来创建复杂的形状。
图1-6展示了一个通过在一个带有渐变色背景的矩形上堆放一个问号来创建的帮助图标。
图1-6StackPane示例
Alignment属性可以管理stackpane中子节点的对齐方式。
这个属性影响所有的子节点,所以margin可以为stack中单独的子节点调整位置。
例1-4 为帮助图标创建一个stackpane
例1-4创建一个StackPane
1.publicvoidaddStackPane(HBoxhb){
2.StackPanestack=newStackPane();
3.RectanglehelpIcon=newRectangle(30.0,25.0);
4.helpIcon.setFill(newLinearGradient(0,0,0,1,true,CycleMethod.NO_CYCLE,
5.newStop[]{
6.newStop(0,Color.web("#4977A3")),
7.newStop(0.5,Color.web("#B0C6DA")),
8.newStop(1,Color.web("#9CB6CF")),}));
9.helpIcon.setStroke(Color.web("#D0E6FA"));
10.helpIcon.setArcHeight(3.5);
11.helpIcon.setArcWidth(3.5);
12.
13.TexthelpText=newText("?
");
14.helpText.setFont(Font.font("Verdana",FontWeight.BOLD,18));
15.helpText.setFill(Color.WHITE);
16.helpText.setStroke(Color.web("#7080A0"));
17.
18.stack.getChildren().addAll(helpIcon,helpText);
19.stack.setAlignment(Pos.CENTER_RIGHT);//子节点右对齐
20.StackPane.setMargin(helpText,newInsets(0,10,0,0));//中间的"?
"
21.
22.hb.getChildren().add(stack);//添加到例1-2中的HBox中
23.HBox.setHgrow(stack,Priority.ALWAYS);//将所有多余空间都交给stack
24.}
例1-4 中的最后几行代码将stackpane添加到了例1-2 中创建的 HBox 窗格,并且总是将它放于窗格的最右边。
结果展示在 图1-7 中。
图1-7HBoxPane中的StackPane
GridPane
GridPane布局窗格能让你创建一个灵活的由行和列组成的网格来放置节点。
节点可以被放于任何单元格内,也可以根据需要横跨多个单元格。
一个gridpane对于创建表单或者任何以行和列组织的布局很有用。
图1-8 展示了一个包含了图标、标题、副标题、正文和图表的gridpane,gridLinesVisible属性可设置是否显示网格线,它能标识出行和列以及行列之间的间隔。
这个属性对于可视化调试你的GridPane很有用。
图1-8GridPane示例
Gap属性可用于管理行和列之间的间隔。
Padding属性可用于管理节点与网格边缘的距离。
Vertical和horizontalalignment属性可用于管理单元格中单独控件的对齐方式。
例1-5 创建了图1-8中的gridpan。
例1-5创建一个GridPane
1.publicGridPaneaddGridPane(){
2.GridPanegrid=newGridPane();
3.grid.setHgap(10);
4.grid.setVgap(10);
5.grid.setPadding(newInsets(0,10,0,10));
6.
7.//Category位于column2,row1
8.Textcategory=newText("Sales:
");
9.category.setFont(Font.font("Arial",FontWeight.BOLD,20));
10.grid.add(category,1,0);
11.
12.//Title位于column3,row1
13.TextchartTitle=newText("CurrentYear");
14.chartTitle.setFont(Font.font("Arial",FontWeight.BOLD,20));
15.grid.add(chartTitle,2,0);
16.
17.//Subtitle位于columns2-3,row2
18.TextchartSubtitle=newText("GoodsandServices");
19.grid.add(chartSubtitle,1,1,2,1);
20.
21.//Houseicon位于column1,rows1-2
22.ImageViewimageHouse=newImageView(
23.newImage(LayoutSample.class.getResourceAsStream("graphics/house.png")));
24.grid.add(imageHouse,0,0,1,2);
25.
26.//Leftlabel位于column1(bottom),row3
27.TextgoodsPercent=newText("Goods\n80%");
28.GridPane.setValignment(goodsPercent,VPos.BOTTOM);
29.grid.add(goodsPercent,0,2);
30.
31.//Chart位于columns2-3,row3
32.ImageViewimageChart=newImageView(
33.newImage(LayoutSample.class.getResourceAsStream("graphics/piechart.png")));
34.grid.add(imageChart,1,2,2,1);
35.
36.//Rightlabel位于column4(top),row3
37.TextservicesPercent=newText("Services\n20%");
38.GridPane.setValignment(servicesPercent,VPos.TOP);
39.grid.add(servicesPercent,3,2);
40.
41.returngrid;
42.}
例1-1 中的 setCenter() 函数将这个gridpane添加到了borderpane的center区域。
结果展示在 图1-9 中。
图1-9BorderPane中的GridPane
当窗口缩放时,gridpane中的节点会根据它们的布局约束进行缩放。
FlowPane
FlowPane 中的节点会连续地排列,并且会在窗格的边界自动换行(或列)。
节点可以垂直地(按列)或水平地(按行)流动。
一个垂直flowpane会在窗格的高度边界上包装节点,一个水平flowpane会在窗格的水平边界上包装节点。
图1-10 展示了一个水平flowpane的例子,里面有多个带有数字的图标。
作为对比,如果把它换成垂直flowpane,第一列会包含1-4号图标,第二列中则包含5-8号图标。
译者注:
包装(wrap),指在窗格的边界上发生自动换行(或换列)。
图1-10水平FlowPane示例
Gap属性可以管理行和列之间的间隔大小。
Padding属性可以管理节点与窗格边界间的距离。
例1-6 为一系列页面图标创建了一个水平flowpane。
例1-6创建一个FlowPane
1.publicFlowPaneaddFlowPane(){
2.FlowPaneflow=newFlowPane();
3.flow.setPadding(newInsets(5,0,5,0));
4.flow.setVgap(4);
5.flow.setHgap(4);
6.flow.setPrefWrapLength(170);//偏好的宽度保证了只有两列
7.flow.setStyle("-fx-background-color:
DAE6F3;");
8.
9.ImageViewpages[]=newImageView[8];
10.for(inti=0;i<8;i++){
11.pages[i]=newImageView(
12.newImage(LayoutSample.class.getResourceAsStream(
13."graphics/chart_"+(i+1)+".png")));
14.flow.getChildren().add(pages[i]);
15.}
16.
17.returnflow;
18.}
例1-1 中的setRight() 函数将这个水平flowpane添加到了borderpane的right区域。
其结果展示在 图1-11 中。
图1-11BorderPane中的FlowPane
TilePane
Tilepane和flowpane很相似。
TilePane 布局将所有的节点放于一个网格中,并且每个单元格(或tile)保持一致的大小。
节点可以水平方式(按行)排列或以竖直方式(按列)排列。
水平布局会在tilepane的宽度边界上包装节点,竖直布局会在高度边界上包装节点。
使用prefColumns 和 prefRows 属性可设定窗格的偏好大小。
Gap属性可以管理行或列之间的间隔。
Padding属性可以管理节点与窗格边界的距离。
例1-7 创建了一个水平tilepane,形成了与 图1-10 一样的布局。
例1-7创建一个TilePane
1.TilePanetile=newTilePane();
2.tile.setPadding(newInsets(5,0,5,0));
3.tile.setVgap(4);
4.tile.setHgap(4);
5.tile.setPrefColumns
(2);
6.tile.setStyle("-fx-background-color:
DAE6F3;");
7.
8.ImageViewpages[]=newImageView[8];
9.for(inti=0;i<8;i++){
10.pages[i]=newImageView(
11.newImage(LayoutSample.class.getResourceAsStream(
12."graphics/chart_"+(i+1)+".png")));
13.tile.getChildren().add(pages[i]);
14.}
AnchorPane
AnchorPane 布局窗格能让你将节点锚定到窗格的顶部、底部、左侧、右侧或者中间。
当窗口缩放时,节点会保持其相对于锚点的位置。
节点可被锚定到多个位置,并且同一位置可以锚定多个节点。
图1-12 展示了一个anchorpane,它带有一个GridPane部分用到的gridpane和一个包含两个按钮的HBox,它们分别被锚定到了窗格的顶部和右下角。
图1-12 AnchorPane示例
例1-8 创建了一个anchorpane,其中有一个节点被锚定到了窗格顶部,另一个节点被锚定到了窗格右下角。
这里用了例1-5 里面创建的gridpane作为top节点。
例1-8创建一个AnchorPane
1.publicAnchorPaneaddAnchorPane(GridPanegrid){
2.AnchorPaneanchorpane=newAnchorPane();
3.ButtonbuttonSave=newButton("Save");
4.ButtonbuttonCancel=newButton("Cancel");
5.
6.HBoxhb=newHBox();
7.hb.setPadding(newInsets(0,10,10,10));
8.hb.setSpacing(10);
9.hb.getChildren().addAll(buttonSave,buttonCancel);
10.
11.anchorpane.getChildren().addAll(grid,hb);//添加例1-5中的gridpane
12.AnchorPane.setBottomAnchor(hb,8.0);
13.AnchorPane.setRightAnchor(hb,5.0);
14.AnchorPane.setTopAnchor(grid,10.0);
15.
16.returnanchorpane;
17.}
下面的语句将borderpane的center区域替换成了这个anchorpane。
1.border.setCenter(addAnchorPane(addGridPane()));
其结果展示在 图1-13 中。
图1-13BorderPane中的AnchorPane
当窗口缩放时,节点会根据它们的锚点保持各自的位置。
从图1-14 中可以看出来,当窗口变小时,被锚定到窗格底部的按钮移动到了离sales信息更近的位置。
图1-14缩放后的AnchorPane
二、控制节点的大小和对齐
使用JavaFx内置布局窗格的一个主要优点是节点的大小和对齐可以交给窗格来完成。
当窗格发生了缩放,节点会依据其偏好的尺寸范围进行缩放。
注意,不是所有节点都可以缩放。
UI控件和布局窗格可以缩放,但是形状、 Text 对象、Group 对象是不可缩放的,它们在布局中被视为刚体。
如果你想要在你的UI中做更多的尺寸控制,你可以直接设置它们的偏好尺寸范围。
然后布局窗格会使用你的这些设定决定控件的尺寸。
要管理控件的位置,你可以使用布局窗格的对齐属性。
本话题针对节点的尺寸控制和对齐控制提供了简单示例。
Layout