当前位置: 代码迷 >> Web前端 >> (通译)第三十回 重置JavaFX2.0结点
  详细解决方案

(通译)第三十回 重置JavaFX2.0结点

热度:239   发布时间:2012-11-23 22:54:33.0
(翻译)第三十回 重置JavaFX2.0结点

?

原文地址http://download.oracle.com/javafx/2.0/layout/size_align.htm

?

?

?

使用JavaFX内置布局窗格最大的好处是窗格帮你管理结点的大小和对其性质。窗格改变大小时,结点大小十分改变要根据窗格的性质。注意不是所有的结点类都可以改变大小。UI控件和布局窗格可以,但是形状、Text对象、 Group对象不可以,它们在布局中是刚性对象。如果你想要更多的控制控件大小,请直接指定其尺寸。布局窗格会根据你的设置来决定控件的大小。

改变结点大小

布局窗格通过调用prefWidth(height)和 prefHeight(width) 方法查询结点的首选尺寸。默认地,UI控件根据其内容计算它们的首选尺寸。比如,Button 对象的尺寸是根据文本长度和标签中字体的尺寸(可能还有图片)计算的。一般的,计算出来的尺寸都是刚好够大以使标签能完全看见。

UI控件也提供根据典型用法的默认最小和最大尺寸。比如,Button 对象的最大尺寸是首选尺寸,因为不太可能让其任意大。然而,ScrollPane 对象的最大尺寸是不确定的,因为总是希望它们会随着内容增长。

既可以使用结点的默认尺寸,也可以随心而设置。比如,Figure 2-1 是边框窗格中一些按钮和列表视图的默认尺寸。

Figure 2-1 Computed Sizes

Description of Figure 2-1 follows
Description of "Figure 2-1 Computed Sizes"

如果想要 Figure 2-2 中的效果呢?里面UI控件的尺寸都是预设的。

Figure 2-2 Desired Sizes

Description of Figure 2-2 follows
Description of "Figure 2-2 Desired Sizes"

应用程序通常需要直接设置控件的最大、最小、首选尺寸。下面将讲解如何修改控件的外观来是自己满意。

让按钮同样大

要实现该目标,可以为每个按钮指定高度和宽度,然后将它们的首选尺寸改成最大的宽度和高度。一种更简单的方法是让布局窗格来完成该工作。布局窗格由想要达到的效果来决定。

使用垂直盒子

?Figure 2-1 中的场景为按钮使用了一个VBox布局窗格且按钮尺寸是默认的。按钮已经具有相同高度了,所以只要改变其宽度即可。

Figure 2-2 中的场景使用一个VBox窗格来利用一下默认行为:让 VBox窗格的宽度和最宽元素的宽度相同。要让按钮都和 VBox窗格宽度相同,就要把每个 按钮的最大宽度设为Double.MAX_VALUE常量,这样控件的变化就没有了限制。当然,把最大值指定为具体指也行,比如 80.0.

Example 2-1 在实现了任何让VBox窗格中的按钮都一样宽。

Example 2-1 Set a Column of Buttons to the Same Width

BorderPane root = new BorderPane();
root.setPadding(new Insets(20, 0, 20, 20));

Button btnAdd = new Button("Add");
Button btnDelete = new Button("Delete");
Button btnMoveUp = new Button("Move Up");
Button btnMoveDown = new Button("Move Down");

btnAdd.setMaxWidth(Double.MAX_VALUE);
btnDelete.setMaxWidth(Double.MAX_VALUE);
btnMoveUp.setMaxWidth(Double.MAX_VALUE);
btnMoveDown.setMaxWidth(Double.MAX_VALUE);

VBox vbButtons = new VBox();
vbButtons.setSpacing(10);
vbButtons.setPadding(new Insets(0, 30, 10, 25)); 
vbButtons.getChildren().addAll(btnAdd, btnDelete, btnMoveUp, btnMoveDown);

root.setright(vbButtons);  

小提示:

把按钮列放在了边框窗格的右部就限制了最宽按钮的首选宽度。边框窗格的中部会尽量去填满所以的控件,所以如果把Vbox放在中间,它和按钮都会扩大。

使用瓦片窗格

?Figure 2-1 中的场景为底部的按钮使用了一个HBox布局窗格且按钮尺寸是默认的。 按钮的款和搞都不同。

Figure 2-2 中的场景使用了一个水平TilePane布局窗格来利用其默认行为:每个细胞或瓦片都相同大小。 每个瓦片的尺寸都需要是瓦片窗格中最大结点的大小。

要让按钮和瓦片尺寸一样,把它们的最大宽度和高度设为Double.MAX_VALUE常量。 Example 2-2 中实现了该目标。

?

Example 2-2 Set a Row of Buttons to the Same Size

Button btnApply = new Button("Apply");
Button btnContinue = new Button("Continue");
Button btnExit = new Button("Exit");

btnApply.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
btnContinue.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
btnExit.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
btnExit.setStyle("-fx-font-size: 14pt;");

TilePane tileButtons = new TilePane(Orientation.HORIZONTAL);
tileButtons.setPadding(new Insets(20, 10, 20, 0));
tileButtons.setHgap(10.0);
tileButtons.getChildren().addAll(btnApply, btnContinue, btnExit);

?

即使窗口改变大小瓦片也不会变,所以瓦片窗格中的按钮不会改变的。

让结点保持首选尺寸

当舞台改变大小时,其中的布局窗格可能会给包含的控件产生过多或不足的空间。每个布局窗格都有其空间分派原则,根据的是控件最小、最大、首选尺寸。一般地,最大尺寸是Double.MAX_VALUE的话控件会扩张来填充空间而有限定大小的就不会。比如, ListView对象最大值不能确定。如果要限制其首选高度,可以设置为 Control.USE_PREF_SIZE 常量,见Example 2-3 .

Example 2-3 Set Maximum Height to Preferred Height

ListView<String> lvList = new ListView<String>();
ObservableList<String> items = FXCollections.observableArrayList (
        "Hot dog", "Hamburger", "French fries", 
        "Carrot sticks", "Chicken salad");
lvList.setItems(items);
lvList.setMaxHeight(Control.USE_PREF_SIZE);

按钮默认只扩张到首选尺寸。但是如果最小宽度没有指定,可能会出现三个点(... ) 。要防止按钮比首选宽度小,把最小宽度设置为其首选宽度。见Example 2-4 .

Example 2-4 Set Minimum Width to Preferred Width

Button btnMoveDown = new Button("Move Down");
btnMoveDown.setMinWidth(Control.USE_PREF_SIZE);

控件的首选尺寸首先基于经过计算(内容)的值。可以覆盖其首选值为自己的选择。下面的语句覆盖了列表的宽度。

lvList.setPrefWidth(150.0);

阻止改变大小

如果不想要结点改变大小,把其最大、最小、首选值设为一样的。要只阻止宽度或高度改变,就把宽度或高度的限制设为相同。在Example 2-5 中,列表创建时要求了限制值相同,所以即使窗口改变其尺寸也不变。一个按钮也限制了宽度的三个值相同。

?

Example 2-5 Set Size Constraints to Prevent Resizing

ListView<String> lvList = new ListView<String>();
lvList.setMinSize(150.0, Control.USE_PREF_SIZE);
lvList.setMaxSize(150.0, Control.USE_PREF_SIZE;

Button btnDelete = new Button("Delete");
btnDelete.setMinWidth(80.0);
btnDelete.setPrefWidth(80.0);
btnDelete.setMaxWidth(80.0);

?

文本对其

每个布局窗格都有自己的方法来对其结点。比如,HBox和 VBox 布局窗格中,结点是顶端对齐和左对齐的。TilePane和 FlowPane窗格中,结点是居中的。窗格自身默认是顶端对齐和左对齐的。

可以使用setAlignment()方法设置结点和窗格的对其方式。对其常量位于 javafx.geometry包中的 enum类型中。

  • HPos - 指定水平对齐的值
  • Pos - 指定垂直和水平对齐的值。下划线左边指定的是垂直对齐值,下划线右边指定的是水平对齐值。比如Pos.BOTTOM_LEFT要结点垂直方向在底部而水平方向在左边。

  • VPos - 指定垂直对齐的值。

Figure 2-3 是代码? Example 2-6 的效果.由于没有对齐限制,布局窗格在左上角。

?

Figure 2-3 Default Positions

Description of Figure 2-3 follows
Description of "Figure 2-3 Default Positions"

?

Example 2-6 Create a UI with Default Alignment

public void start(Stage primaryStage) {
    GridPane grid = new GridPane();
    grid.setHgap(10);
    grid.setVgap(12);

    HBox hbButtons = new HBox();
    hbButtons.setSpacing(10.0);

    Button btnSubmit = new Button("Submit");
    Button btnClear = new Button("Clear");
    Button btnExit = new Button("Exit");
    btnSubmit.setStyle("-fx-font-size: 11pt;");

    Label lblName = new Label("User name:");
    TextField tfName = new TextField();
    Label lblPwd = new Label("Password:");
    PasswordField pfPwd = new PasswordField();

    hbButtons.getChildren().addAll(btnSubmit, btnClear, btnExit);
    grid.add(lblName, 0, 0);
    grid.add(tfName, 1, 0);
    grid.add(lblPwd, 0, 1);
    grid.add(pfPwd, 1, 1);
    grid.add(hbButtons, 0, 2, 2, 1);
    Scene scene = new Scene(grid, 250, 250);
    primaryStage.setTitle("Layout Positioning");
    primaryStage.setScene(scene);
    primaryStage.show();
}

如果要 Figure 2-4 中的效果呢?窗格在屏幕中央。

?

Figure 2-4 Desired Positions

Description of Figure 2-4 follows
Description of "Figure 2-4 Desired Positions"

?

下面就讲述任何覆盖默认位置设置。

将网格居中

要让 Example 2-6 中的网格居中,这样做:

grid.setAlignment(Pos.CENTER);

对齐列中的控件

在我们的理想布局中,标签要右对齐而文本框左对齐。要在网格中达到该目的,为每列使用ColumnConstraints类并设置水平对其方式。 Example 2-7 为 Example 2-6 中的网格定义了列属性。

Example 2-7 Define the Columns in the Grid

GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER);
grid.setHgap(10);
grid.setVgap(12);

ColumnConstraints column1 = new ColumnConstraints();
column1.setHalignment(HPos.RIGHT);
grid.getColumnConstraints().add(column1); 

ColumnConstraints column2 = new ColumnConstraints();
column2.setHalignment(HPos.LEFT);
grid.getColumnConstraints().add(column2); 

?使用VBox窗格也可以实现控件右对齐。照下面这样使用 setAlignment() 方法:

VBox vbox = new VBox;
vbox.setAlignment(Pos.CENTER_RIGHT);

按钮居中

?HBox中的按钮跨越了网格的列。下面的代码让按钮居中:

HBox hbButtons = new HBox()
hbButtons.setAlignment(Pos.CENTER);

HBoxsetAlignment() 方法居中了HBox窗格和其中的结点。要是更喜欢将 HBox窗格行居中而其中的按钮底部对齐,就像 Figure 2-5 .

Figure 2-5 Override Positions and Bottom-Justify the Buttons

Description of Figure 2-5 follows
Description of "Figure 2-5 Override Positions and Bottom-Justify the Buttons"

要这样安排,把 HBox 窗格放在一个只有一个细胞的内网格中,再把它放在外网格的第三行。把内网格设置为居中,把HBox窗格设为底部对齐,见 Example 2-8 .

Example 2-8 Center and Bottom-Justify the Buttons

HBox hbButtons = new HBox();
hbButtons.setSpacing(10.0);
hbButtons.setAlignment(Pos.BOTTOM_CENTER);
hbButtons.getChildren().addAll(btnSubmit, btnClear, btnExit);

GridPane innergrid = new GridPane();
innergrid.setAlignment(Pos.CENTER);
innergrid.add(hbButtons, 0, 0);
grid.add(innergrid, 0, 2, 2, 1);
1 楼 sorradawnstar 2011-12-29  
你好, 我读了你翻译的JavaFX教程. 有个问题请教一下: PrefSize, MinSize, MaxSize有什么关系啊? 我想指定一个控件的大小, 用setMinSize不成功, 用setPrefSize却成功了.

我的邮箱: dawnstar@163.com
2 楼 somefuture 2011-12-30  
sorradawnstar 写道
你好, 我读了你翻译的JavaFX教程. 有个问题请教一下: PrefSize, MinSize, MaxSize有什么关系啊? 我想指定一个控件的大小, 用setMinSize不成功, 用setPrefSize却成功了.

我的邮箱: dawnstar@163.com

非常感谢你关注JavaFX2。
Pref是一个控件初始化时的推荐大小。
如果一个控件大小会变化(可能是里面的内容变化了,或者是父控件变化了,等等),还需要指定max和min。
这样当它变化时,它的尺寸会限制在某个区间内,不至于太大(和太小)。