在JavaFX中使用布局资料.docx
《在JavaFX中使用布局资料.docx》由会员分享,可在线阅读,更多相关《在JavaFX中使用布局资料.docx(23页珍藏版)》请在冰豆网上搜索。
在JavaFX中使用布局资料
在JavaFX中使用布局
一、用内置布局窗格
一个JavaFx应用可以通过设置每个UI元素的位置和大小来手动地布局用户界面。
但是,一个更简单的做法是使用布局窗格。
JavaFx SDK提供了多种布局容器类,叫做窗格,它们可简化对一些经典布局的设置和管理,例如行、列、堆叠、平铺等等。
当窗口缩放时,布局窗格会自动地根据节点属性重设其包含的所有节点的位置和大小。
本话题为JavaFx layout包中提供的的每个布局窗格都给出了相应的概述和简单的示例。
LayoutSample.java文件包含了本话题中UI的源码。
LayoutSample.zip文件包含了示例应用的NetBeans工程。
BorderPane
BorderPane布局窗格提供了5个放置节点的区域:
top, bottom, left, right, 和 center。
图1-1展示了border pane构建的布局样式。
这些区域可以是任意大小,如果应用不需要某个区域,你可以不定义它,然后窗格就不会给这个区域分配空间。
图 1-1 Border Pane 示例
border pane可用于这种经典的外观:
top:
工具栏,bottom:
状态栏,left:
导航栏,right:
附加信息,center:
工作区。
默认情况下,如果窗口比所有区域所需空间还大,多余的空间将被分配给中间区域。
如果窗口比所需空间小,区域可能会重叠。
重叠是由区域设置的顺序决定的。
例如,如果区域设置的顺序是 left, bottom, right,当窗口变得更小时,bottom区域会覆盖left区域,right区域会覆盖bottom区域。
如果区域设置的顺序是 left, right, bottom,当窗口变得更小时,bottom区域会覆盖left和right区域。
例1-1 展示了布局示例应用中创建border pane的代码。
创建每个区域用到的布局窗格的函数会在本话题的剩余部分介绍。
例 1-1 创建一个 Border Pane
1. BorderPane border = new BorderPane();
2. HBox hbox = addHBox()
3. border.setTop(hbox);
4. border.setLeft(addVBox());
5. addStackPane(hbox); // 在top区域的HBox中添加stack pane
6.
7. border.setCenter(addGridPane());
8. border.setRight(addFlowPane());
注意一点,在本例中,border pane的bottom区域并没有被使用。
如果你想要在bottom区域中添加什么,可以使用下面的语句并且替换其中的节点node为你选择的控件。
1. border.setBottom(node);
HBox
HBox 布局窗格可以让你很容易地将一系列节点排列到一行中。
图1-2 展示了一个 HBox 窗格的例子.
图 1-2 HBox 窗格示例
Padding 属性可以设置节点到 HBox 边缘的距离。
Spacing 可以管理节点之间的距离。
Style可用来改变背景色。
例1-2 为一个工具栏创建了一个包含两个按钮的 HBox 窗格。
例 1-2 创建一个 HBox 窗格
1. public HBox addHBox() {
2. HBox hbox = new HBox();
3. hbox.setPadding(new Insets(15, 12, 15, 12));
4. hbox.setSpacing(10);
5. hbox.setStyle("-fx-background-color:
#336699;");
6.
7. Button buttonCurrent = new Button("Current");
8. buttonCurrent.setPrefSize(100, 20);
9.
10. Button buttonProjected = new Button("Projected");
11. buttonProjected.setPrefSize(100, 20);
12. hbox.getChildren().addAll(buttonCurrent, buttonProjected);
13.
14. return hbox;
15. }
例1-1中的 setTop() 函数将这个 HBox 窗格添加到border pane的top区域。
其结果展示在图1-3中。
图 1-3 Border Pane 中的 HBox Pane
VBox
VBox 布局窗格和 HBox 很相似,除了这里所有节点是被排列到一个列中的。
图1-4 展示了一个 VBox 窗格的示例。
图 1-4 VBox Pane示例
Padding 可用于设置节点到 VBox 窗格边界的距离。
Spacing可管理节点之间的距离。
Margins 可在单独的控件周围添加额外的空间。
译者注:
padding又称内边距、补白或留白,margin又称外边距、边界或额外空白区。
它们的概念来源于CSS,即层叠样式表。
从一般意义上讲,margin是用来隔开元素与元素的间距;padding是用来隔开元素与内容的间隔。
margin用于布局分开元素使元素与元素互不相干;padding用于元素与内容之间的间隔,让内容(文字)与(包裹)元素之间有一段“呼吸距离”。
(参考文章)
例1-3 创建了一个包含一列选项的 VBox 窗格。
例 1-3 创建一个VBox Pane
1. public VBox addVBox(); {
2. VBox vbox = new VBox();
3. vbox.setPadding(new Insets(10));
4. vbox.setSpacing(8);
5.
6. Text title = new Text("Data");
7. title.setFont(Font.font("Arial", FontWeight.BOLD, 14));
8. vbox.getChildren().add(title);
9.
10. Hyperlink options[] = new Hyperlink[] {
11. new Hyperlink("Sales"),
12. new Hyperlink("Marketing"),
13. new Hyperlink("Distribution"),
14. new Hyperlink("Costs")};
15.
16. for (int i=0; i<4; i++) {
17. VBox.setMargin(options[i], new Insets(0, 0, 0, 8));
18. vbox.getChildren().add(options[i]);
19. }
20.
21. return vbox;
22. }
例1-1 中的 setLeft() 函数将这个 VBox 窗格添加到了border pane的left区域。
其结果展示在 图1-5 中。
图 1-5 Border Pane 中的 VBox Pane
StackPane
StackPane 布局窗格能将所有的节点放到一个堆栈中,其中每一个新的节点被添加到前一个节点的上方。
这个布局模型能让你很容易地在一个形状或图像上面覆盖一个文本,或者用常用形状互相覆盖来创建复杂的形状。
图1-6展示了一个通过在一个带有渐变色背景的矩形上堆放一个问号来创建的帮助图标。
图 1-6 Stack Pane 示例
Alignment 属性可以管理stack pane中子节点的对齐方式。
这个属性影响所有的子节点,所以margin可以为stack中单独的子节点调整位置。
例1-4 为帮助图标创建一个stack pane
例 1-4 创建一个 Stack Pane
1. public void addStackPane(HBox hb) {
2. StackPane stack = new StackPane();
3. Rectangle helpIcon = new Rectangle(30.0, 25.0);
4. helpIcon.setFill(new LinearGradient(0,0,0,1, true, CycleMethod.NO_CYCLE,
5. new Stop[]{
6. new Stop(0,Color.web("#4977A3")),
7. new Stop(0.5, Color.web("#B0C6DA")),
8. new Stop(1,Color.web("#9CB6CF")),}));
9. helpIcon.setStroke(Color.web("#D0E6FA"));
10. helpIcon.setArcHeight(3.5);
11. helpIcon.setArcWidth(3.5);
12.
13. Text helpText = new Text("?
");
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, new Insets(0, 10, 0, 0)); // 中间的 "?
"
21.
22. hb.getChildren().add(stack); // 添加到 例1-2 中的HBox中
23. HBox.setHgrow(stack, Priority.ALWAYS); // 将所有多余空间都交给stack
24. }
例1-4 中的最后几行代码将stack pane添加到了例1-2 中创建的 HBox 窗格,并且总是将它放于窗格的最右边。
结果展示在 图1-7 中。
图 1-7 HBox Pane 中的 Stack Pane
GridPane
GridPane布局窗格能让你创建一个灵活的由行和列组成的网格来放置节点。
节点可以被放于任何单元格内,也可以根据需要横跨多个单元格。
一个grid pane对于创建表单或者任何以行和列组织的布局很有用。
图1-8 展示了一个包含了图标、标题、副标题、正文和图表的grid pane,gridLinesVisible属性可设置是否显示网格线,它能标识出行和列以及行列之间的间隔。
这个属性对于可视化调试你的GridPane很有用。
图 1-8 Grid Pane示例
Gap属性可用于管理行和列之间的间隔。
Padding属性可用于管理节点与网格边缘的距离。
Vertical和horizontal alignment属性可用于管理单元格中单独控件的对齐方式。
例1-5 创建了图1-8中的grid pan。
例 1-5 创建一个 Grid Pane
1. public GridPane addGridPane() {
2. GridPane grid = new GridPane();
3. grid.setHgap(10);
4. grid.setVgap(10);
5. grid.setPadding(new Insets(0, 10, 0, 10));
6.
7. // Category 位于 column 2, row 1
8. Text category = new Text("Sales:
");
9. category.setFont(Font.font("Arial", FontWeight.BOLD, 20));
10. grid.add(category, 1, 0);
11.
12. // Title 位于 column 3, row 1
13. Text chartTitle = new Text("Current Year");
14. chartTitle.setFont(Font.font("Arial", FontWeight.BOLD, 20));
15. grid.add(chartTitle, 2, 0);
16.
17. // Subtitle 位于 columns 2-3, row 2
18. Text chartSubtitle = new Text("Goods and Services");
19. grid.add(chartSubtitle, 1, 1, 2, 1);
20.
21. // House icon 位于 column 1, rows 1-2
22. ImageView imageHouse = new ImageView(
23. new Image(LayoutSample.class.getResourceAsStream("graphics/house.png")));
24. grid.add(imageHouse, 0, 0, 1, 2);
25.
26. // Left label 位于 column 1 (bottom), row 3
27. Text goodsPercent = new Text("Goods\n80%");
28. GridPane.setValignment(goodsPercent, VPos.BOTTOM);
29. grid.add(goodsPercent, 0, 2);
30.
31. // Chart 位于 columns 2-3, row 3
32. ImageView imageChart = new ImageView(
33. new Image(LayoutSample.class.getResourceAsStream("graphics/piechart.png")));
34. grid.add(imageChart, 1, 2, 2, 1);
35.
36. // Right label 位于 column 4 (top), row 3
37. Text servicesPercent = new Text("Services\n20%");
38. GridPane.setValignment(servicesPercent, VPos.TOP);
39. grid.add(servicesPercent, 3, 2);
40.
41. return grid;
42. }
例1-1 中的 setCenter() 函数将这个grid pane添加到了border pane的center区域。
结果展示在图1-9 中。
图 1-9 Border Pane中的Grid Pane
当窗口缩放时,grid pane中的节点会根据它们的布局约束进行缩放。
FlowPane
FlowPane 中的节点会连续地排列,并且会在窗格的边界自动换行(或列)。
节点可以垂直地(按列)或水平地(按行)流动。
一个垂直flow pane会在窗格的高度边界上包装节点,一个水平flow pane会在窗格的水平边界上包装节点。
图1-10 展示了一个水平flow pane的例子,里面有多个带有数字的图标。
作为对比,如果把它换成垂直flow pane,第一列会包含1-4号图标,第二列中则包含5-8号图标。
译者注:
包装(wrap),指在窗格的边界上发生自动换行(或换列)。
图 1-10 水平 Flow Pane 示例
Gap属性可以管理行和列之间的间隔大小。
Padding属性可以管理节点与窗格边界间的距离。
例1-6为一系列页面图标创建了一个水平flow pane。
例 1-6 创建一个 Flow Pane
1. public FlowPane addFlowPane() {
2. FlowPane flow = new FlowPane();
3. flow.setPadding(new Insets(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. ImageView pages[] = new ImageView[8];
10. for (int i=0; i<8; i++) {
11. pages[i] = new ImageView(
12. new Image(LayoutSample.class.getResourceAsStream(
13. "graphics/chart_"+(i+1)+".png")));
14. flow.getChildren().add(pages[i]);
15. }
16.
17. return flow;
18. }
例1-1中的setRight() 函数将这个水平flow pane添加到了border pane的right区域。
其结果展示在 图1-11 中。
图 1-11 Border Pane 中的 Flow Pane
TilePane
Tile pane 和 flow pane 很相似。
TilePane 布局将所有的节点放于一个网格中,并且每个单元格(或tile)保持一致的大小。
节点可以水平方式(按行)排列或以竖直方式(按列)排列。
水平布局会在tile pane的宽度边界上包装节点,竖直布局会在高度边界上包装节点。
使用prefColumns 和 prefRows 属性可设定窗格的偏好大小。
Gap属性可以管理行或列之间的间隔。
Padding属性可以管理节点与窗格边界的距离。
例1-7 创建了一个水平tile pane,形成了与 图1-10 一样的布局。
例 1-7 创建一个Tile Pane
1. TilePane tile = new TilePane();
2. tile.setPadding(new Insets(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. ImageView pages[] = new ImageView[8];
9. for (int i=0; i<8; i++) {
10. pages[i] = new ImageView(
11. new Image(LayoutSample.class.getResourceAsStream(
12. "graphics/chart_"+(i+1)+".png")));
13. tile.getChildren().add(pages[i]);
14. }
AnchorPane
AnchorPane 布局窗格能让你将节点锚定到窗格的顶部、底部、左侧、右侧或者中间。
当窗口缩放时,节点会保持其相对于锚点的位置。
节点可被锚定到多个位置,并且同一位置可以锚定多个节点。
图1-12 展示了一个anchor pane,它带有一个GridPane部分用到的grid pane和一个包含两个按钮的HBox,它们分别被锚定到了窗格的顶部和右下角。
图 1-12 Anchor Pane 示例
例1-8 创建了一个anchor pane,其中有一个节点被锚定到了窗格顶部,另一个节点被锚定到了窗格右下角。
这里用了例1-5 里面创建的grid pane作为top节点。
例 1-8 创建一个 Anchor Pane
1. public AnchorPane addAnchorPane(GridPane grid) {
2. AnchorPane anchorpane = new AnchorPane();
3. Button buttonSave = new Button("Save");
4. Button buttonCancel = new Button("Cancel");
5.
6. HBox hb = new HBox();
7. hb.setPadding(new Insets(0, 10, 10, 10));
8. hb.setSpacing(10);
9. hb.getChildren().addAll(buttonSave, buttonCancel);
10.
11. anchorpane.getChildren().addAll(grid,hb); // 添加 例1-5中的 grid pane
12. AnchorPane.setBottomAnchor(hb, 8.0);
13. AnchorPane.setRightAnchor(hb, 5.0);
14. AnchorPane.setTopAnchor(grid, 10.0);
15.
16. return anchorpane;
17. }
下面的语句将border pane的center区域替换成了这个anchor pane。
1. border.setCenter(addAnchorPane(addGridPane()));
其结果展示在 图1-13 中。
图 1-13 Border Pane 中的 Anchor Pane
当窗口缩放时,节点会根据它们的锚点保持各自的位置。
从图1-14 中可以