Java開發筆記(一百四十五)FXML布局的伸展適配


前面介紹了FXML的基本格式及其控制器的用法,算是打通了FXML方式的編碼流程。程序界面通常保持固定尺寸,不過有時也允許用戶拖曳窗口大小,不拖不打緊,一拖就可能壞事。像之前的登錄窗口,沒拖的時候界面如下圖所示。


現在開始慢慢把窗口拖長,拖到一半停下來,此時登錄界面如下圖所示。


乍看過去,界面上的各控件大小保持不變,且始終居中顯示,沒發現什么問題。可是繼續拖長窗口,突然之間這些控件乾坤大挪移,用戶名區域頂到了第一行,登錄按鈕跟着頂到了第二行,變化后的界面效果如下圖所示。


之所以出現控件排版錯亂的問題,是因為該界面的根節點采用了流式窗格FlowPane。所謂流式,指的是從左到右排列,倘若沒排滿一行,就跟在當前行后面;只有排滿了一行,才會另起一行繼續排。剛剛拖拉窗口的時候,拖得太長了,導致窗口的寬度能夠容納登錄類型與用戶名兩個區域,結果兩塊區域便擠到同一行了。顯然這不是期望的界面布局,至少控件要老老實實呆在自己的位置,不可越雷池一步。
若想避免流式窗格排版飄忽的問題,可以使用垂直箱子VBox替換流式窗格,垂直箱子規定它的每個直接下級都占用一行,絕對不會產生兩個直接下級擠在同一行的現象。於是修改原來的fxml文件,把根節點FlowPane換成VBox,對應的xml標簽變為以下格式:

<VBox fx:controller="com.javafx.fxml.LoginController" xmlns:fx="http://javafx.com/fxml" alignment="center">
  <!-- 這是xml注釋標記。中間省略登錄窗口的各控件標簽 -->
</VBox>

 

fxml文件修改完畢,重新運行測試程序,彈出的登錄窗口如下圖所示。


現在不管怎樣拉長窗口,各區域都留在當前行,再也不會亂跑了。然而采用VBox的界面很不協調,緣由在於VBox不支持hgap與vgap屬性,因此各控件之間沒能自動分隔開,幾乎都粘在一起了,例如:
1、登錄類型、用戶名、密碼三塊區域的左側直接頂到了窗口邊緣;
2、用戶名輸入框、密碼輸入框、登錄按鈕三個自上往下緊緊貼着,不留一絲空隙;
似此過於緊湊的界面,令人感覺頗為拘謹,還是留個適當的間隔比較好。雖然VBox不支持hgap與vgap屬性,但它另外提供了padding屬性組,允許分別指定上、下、左、右四個方向的間距。padding節點掛在哪個VBox或HBox之下,就表示哪個箱子會在內部自動留白,padding對應的xml標簽具體寫法如下所示:

  <padding>
    <Insets top="10.0" bottom="10.0" left="10.0" right="10.0"/>
  </padding>

 

上述的padding節點例子,定義了在上、下、左、右四個方向各留出10個像素的空白間距。考慮到VBox和HBox下面可能掛着好幾個子控件,為了更好地將這些子控件跟padding區分開,fxml又給VBox和HBox引入了children子節點,凡是下級控件統統放到children節點之下,而padding節點專門放置四個方向的間隔距離。如此一來,形態完整的VBox節點結構變成了以下這般:

<VBox fx:controller="com.javafx.fxml.LoginController" xmlns:fx="http://javafx.com/fxml" alignment="center">
  <children>
    <!-- 這是xml注釋標記。中間省略VBox的下級控件列表 -->
  </children>
  <padding>
    <Insets top="10.0" bottom="10.0" left="10.0" right="10.0"/>
  </padding>
</VBox>

 

由上面的xml樣例可以看到,改進之后的VBox標簽變得層次分明、結構清晰,大大增強了它的可讀性。
除此之外,fxml還為VBox和HBox提供了自動伸展功能,也就是說,隨着窗口尺寸的增大,VBox和HBox的寬高也會隨之增大。其中水平方向的寬度自適應,由屬性HBox.hgrow控制,其值為ALWAYS時表示當前箱子的寬度跟隨上級變化;垂直方向的寬度自適應則由屬性VBox.vgrow控制,其值為ALWAYS時表示當前箱子的高度跟隨上級變化。尤其需要注意的是,除了VBox和HBox這兩個箱子支持自動伸展以外,只有幾個輸入框控件支持自動伸展,其中TextField與PasswordField只支持水平方向上的自動伸展,而TextArea同時支持水平與垂直兩個方向的自動伸展。
利用fxml的幾個新節點和新屬性改造原先的登錄界面,一方面,整個登錄界面在窗口四周邊緣均留白,各行之間也留出一條縫隙;另一方面,令用戶名輸入框和密碼輸入框支持水平伸展,令用戶名區域和密碼區域支持垂直伸展。這么改造一番之后的fxml文件示例如下:

<VBox fx:controller="com.javafx.fxml.LoginController" xmlns:fx="http://javafx.com/fxml" alignment="center">
  <children>
    <HBox fx:id="hbType" prefWidth="400" prefHeight="40">
      <children>
        <Label fx:id="labelType" prefWidth="120" prefHeight="40" text="登錄類型:" />
        <fx:define>
            <ToggleGroup fx:id="tgType" />
        </fx:define>
        <RadioButton fx:id="rbPassword" prefWidth="140" prefHeight="40" toggleGroup="$tgType"
            text="密碼登錄" selected="true" />
        <RadioButton fx:id="rbVerifycode" prefWidth="140" prefHeight="40" toggleGroup="$tgType"
            text="驗證碼登錄" />
      </children>
      <padding>
        <Insets top="0.0" bottom="10.0" left="0.0" right="0.0"/>
      </padding>
    </HBox>
    <HBox fx:id="hbUser" prefWidth="400" prefHeight="40" VBox.vgrow="ALWAYS">
      <children>
        <Label fx:id="labelUser" prefWidth="120" prefHeight="40" text="用戶名:" />
        <TextField fx:id="fieldUser" prefWidth="280" prefHeight="40" HBox.hgrow="ALWAYS" />
      </children>
      <padding>
        <Insets top="0.0" bottom="10.0" left="0.0" right="0.0"/>
      </padding>
    </HBox>
    <HBox fx:id="hbPassword" prefWidth="400" prefHeight="40" VBox.vgrow="ALWAYS">
      <children>
        <Label fx:id="labelPassword" prefWidth="120" prefHeight="40" text="密 碼:" />
        <PasswordField fx:id="fieldPassword" prefWidth="280" prefHeight="40" HBox.hgrow="ALWAYS" />
      </children>
      <padding>
        <Insets top="0.0" bottom="10.0" left="0.0" right="0.0"/>
      </padding>
    </HBox>
    <Button fx:id="btnLogin" prefWidth="400" prefHeight="40" text="登  錄" />
    <Label fx:id="labelLoginResult" prefWidth="400" prefHeight="40" text="這里顯示登錄結果" />
  </children>
  <padding>
    <Insets top="10.0" bottom="10.0" left="10.0" right="10.0"/>
  </padding>
</VBox>

 

再次運行測試程序,彈出的登錄窗口如下圖所示,果然各級控件與周邊都隔了一小段距離。


接着在水平方向拉長窗口,拉長之后的窗口界面如下面左圖所示。回到初始尺寸,在垂直方向拉高窗口,拉高之后的如下面右圖所示。


從上面兩張效果圖可見,幾個箱子和輸入框的寬高確實跟隨窗口尺寸的變化而變化。



更多Java技術文章參見《Java開發筆記(序)章節目錄


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM