2014年2月10日 星期一

JavaFX HBox and VBox

HBoxVBox類似於Java Swing的Box Layout。Box Layout配置物件的方式分為水平 (由左至右) 與垂直 (由上至下) 兩種,分別由BoxLayout.X_AXISBoxLayout.Y_AXIS常數值設定。此外,在使用Box Layout配置物件時,可搭配javax.swing.Box類別一起使用,以定義容器中各物件間的間隔距離,Box類別分別提供Glue、Rigid Area、Strut及自訂Filler四種方式定義間隔距離。

以水平配置為例,Box Layout會嘗試調整物件的寬度為其最佳寬度 (Preferred Width),當容器的寬度不足時,Box Layout會自動調整物件的寬度以儘量符合容器的寬度限制,另外Box Layout以其中高度最大的物件之最佳高度 (Preferred Height) 為基準,調整各物件的高度使其一致。

以垂直配置為例,Box Layout會嘗試調整物件的高度為其最佳高度 (Preferred Height),當容器的高度不足時,Box Layout會自動調整物件的高度以儘量符合容器的高度限制,另外Box Layout以其中寬度最大的物件之最佳寬度 (Preferred Width) 為基準,調整各物件的寬度使其一致。

下圖是以Box Layout分別由左至右與由上至下配置物件:
JavaFX的HBoxVBox類似於Box Layout的水平與垂直配置方式,但使用上不需複雜的參數設定,較Box Layout簡易。

HBox是以水平方向依序配置物件,以HBox配置物件時,HBox會嘗試調整各物件的寬度為其最佳寬度 (Preferred Width),並依其fillHeight屬性之設定 (若為true) 調整各物件的高度為其最佳高度 (Preferred Height)。HBox預設之對齊方式為水平方向靠左對齊、垂直方向向上對齊 (Pos.TOP_LEFT)。此外,可透過「水平增加優先順序」 (Horizontal Grow Priority,簡稱hgrow) 之設定,調整因視窗或Java Applet大小改變時,物件之寬度是否隨之改變。

HBox類別的建構函式為:

  public HBox()
  public HBox(double spacing)

其中參數spacing用以設定HBox中各物件間的水平間隔距離,而第一個建構函式無任何參數,其預設之水平間隔距離為0。

請參考以下範例:


HBox hbox = new HBox();
hbox.setPadding(new Insets(20, 10, 10, 10));
hbox.setSpacing(10);

Label lblURL = new Label("URL:");

TextField txtURL = new TextField();
// 設定HBox中物件的「水平增加優先順序」(hgrow)
hbox.setHgrow(txtURL, Priority.ALWAYS);

Button btnGo = new Button("Go");
btnGo.setPrefSize(60, 20);

// 將所有物件加至HBox之中
hbox.getChildren().addAll(lblURL, txtURL, btnGo);


【程式說明】

範例示範如何以HBox配置物件,首先以setSpacing()方法設定HBox中各物件間的水平間隔距離。特別是在配置文字欄位 (TextField) 時,設定其「水平增加優先順序」 (hgrow) 為Priority.ALWAYS,當視窗或Java Applet大小改變時,文字欄位將隨之改變其寬度,請參考以下的執行結果。

【執行結果】
由於設定文字欄位的「水平增加優先順序」 (hgrow) 為Priority.ALWAYS,因此當視窗大小改變時,只有文字欄位的寬度將隨之改變,其餘物件的寬度則保持不變。
VBox是以垂直方向依序配置物件,以VBox配置物件時,VBox會嘗試調整各物件的高度為其最佳高度 (Preferred Height),並依其fillWidth屬性之設定 (若為true) 調整各物件的寬度為其最佳寬度 (Preferred Width)。VBox預設之對齊方式為水平方向靠左對齊、垂直方向向上對齊 (Pos.TOP_LEFT)。此外,可透過「垂直增加優先順序」 (Vertical Grow Priority,簡稱vgrow) 之設定,調整因視窗或Java Applet大小改變時,物件之高度是否隨之改變。

VBox類別的建構函式為:

  public VBox()
  public VBox(double spacing)

其中參數spacing用以設定VBox中各物件間的垂直間隔距離,而第一個建構函式無任何參數,其預設之垂直間隔距離為0。

請參考以下範例:


VBox vbox = new VBox();
vbox.setPadding(new Insets(10, 10, 10, 10));
vbox.setSpacing(10); 

Label label1 = new Label("Month");
label1.setFont(Font.font("Verdana", FontWeight.BOLD, 12));
vbox.getChildren().add(label1);

ListView<String> list = new ListView<>();

ObservableList<String> months =
  FXCollections.observableArrayList(
    "January", "February", "March", "April", 
    "May", "June", "July", "August", 
    "September", "October", "November", "December");

list.setItems(months);

// 設定VBox中物件的「垂直增加優先順序」(vgrow)
vbox.setVgrow(list, Priority.ALWAYS);
// 將ListView物件加至VBox之中
vbox.getChildren().add(list);


【程式說明】

範例3-15示範如何以VBox配置物件,首先以setSpacing()方法設定VBox中各物件間的垂直間隔距離。特別是在配置檢視清單 (ListView) 時,設定其「垂直增加優先順序」 (vgrow) 為Priority.ALWAYS,當視窗或Java Applet大小改變時,檢視清單將隨之改變其高度,請參考以下的執行結果。

【執行結果】
由於設定檢視清單的「垂直增加優先順序」 (vgrow) 為Priority.ALWAYS,因此當視窗大小改變時,只有檢視清單的高度將隨之改變,其餘物件的高度則保持不變。
除了HBoxVBox類別之外,JavaFX分別提供HBoxBuilderVBoxBuilder類別配置物件。

HBoxBuilder配置物件,首先以create()方法建立HBoxBuilder的實體 (Instance),最後再以build()方法以HBoxBuilder物件建立HBox的實體,其間以alignment()fillHeight()spacing()等方法分別設定水平與垂直對齊方式、是否調整各物件的高度為其最佳高度、各物件間的水平間隔距離等,再以children()方法將物件置於HBox區域中,例如以下範例


Label lblURL = new Label("URL:");

TextField txtURL = new TextField();
txtURL.setPrefSize(160, 20);

Button btnGo = new Button("Go");
btnGo.setPrefSize(60, 20);

// 建立SceneBuilder的實體(Instance)
Scene scene = SceneBuilder.create()
  .width(300)
  .height(100)
  .root(
    // 建立HBoxBuilder的實體(Instance)
    HBoxBuilder.create()
      .alignment(Pos.TOP_LEFT)
      .spacing(10)
      .padding(new Insets(20, 10, 10, 10))
      // 將物件置於HBox中
      .children(lblURL, txtURL, btnGo)
      // 以HBoxBuilder物件建立HBox的實體(Instance)
      .build()
  )
  .build();

// 設定HBox中物件的「水平增加優先順序」(hgrow)
HBox.setHgrow(txtURL, Priority.ALWAYS);


VBoxBuilder配置物件的程式架構如下,首先以create()方法建立VBoxBuilder的實體 (Instance),最後再以build()方法以VBoxBuilder物件建立VBox的實體,其間以alignment()fillWidth()spacing()等方法分別設定水平與垂直對齊方式、是否調整各物件的寬度為其最佳寬度、各物件間的垂直間隔距離等,再以children()方法將物件置於VBox區域中,例如以下範例


Label label1 = new Label("Month");
label1.setFont(Font.font("Verdana", FontWeight.BOLD, 12));

ListView<String> list = new ListView<>();

ObservableList<String> months =
  FXCollections.observableArrayList(
    "January", "February", "March", "April", 
    "May", "June", "July", "August", 
    "September", "October", "November", "December");

list.setItems(months);

// 建立SceneBuilder的實體(Instance)
Scene scene = SceneBuilder.create()
  .width(250)
  .height(250)
  .root(
    // 建立VBoxBuilder的實體(Instance)
    VBoxBuilder.create()
      .alignment(Pos.TOP_LEFT)
      .spacing(10)
      .padding(new Insets(10, 10, 10, 10))
      // 將物件置於VBox中
      .children(label1, list)
      // 以VBoxBuilder物件建立VBox的實體(Instance)
      .build()
  )
  .build();

// 設定VBox中物件的「垂直增加優先順序」(vgrow)
VBox.setVgrow(list, Priority.ALWAYS);


【參考資料】

[1] 黃嘉輝,深入研究JavaFX 2。
[2] 黃嘉輝,深入研究Java Swing。
[3] Java Official Web Site:http://www.oracle.com/technetwork/java/index.html
[4] JavaFX:http://www.oracle.com/technetwork/java/javafx
[5] JavaFX 2.2 API Specification.
[6] Java Platform, Standard Edition 7 API Specification.

© Chia-Hui Huang

沒有留言:

張貼留言