Java開發筆記(一百四十三)FXML布局的基本格式


前面介紹了JavaFX的常見控件用法,雖然JavaFX控件比起AWT與Swing要好用些,但是一樣通過代碼編寫控件界面,並沒有提高什么開發效率。要想瀏覽界面的展示效果,都必須運行測試程序才能觀看,即使只是微調控件的大小,也得重新運行程序查看效果,顯然既費時又費力。為此JavaFX提供了另一種給界面排版的方式,不必使用Java代碼堆砌控件,而是利用FXML文件開展界面布局,同時借助於idea的預覽功能,無需運行程序即可直接觀察FXML的布局效果。所謂“FXML”意思是JavaFX專用的XML格式,它基於XML標准並加以擴展,每個JavaFX控件均有對應的XML標簽,把這些蘊含控件的標簽組裝起來,便形成了一個窗口界面專屬的布局文件。
舉個簡單的例子,現在准備畫登錄界面,包含用戶名輸入框、密碼輸入框,以及登錄按鈕,這些控件自上往下分成三行排列。該界面預期的展示效果如下圖所示。

 

倘若完全使用代碼實現以上的登錄界面,無疑要反復地調整代碼並多次執行程序,才能達到滿意的布局效果。那么采用FXML方式的話,可以把與界面相關的控件元素剝離出來,改為在FXML文件中書寫XML標簽結構。比如上述登錄頁對應的FXML文件名叫login.fxml,其內容示例如下:

<?import javafx.scene.layout.FlowPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.PasswordField?>

<FlowPane xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="5" vgap="5">
	<HBox fx:id="hbUser" prefWidth="400" prefHeight="40">
		<Label fx:id="labelUser" prefWidth="120" prefHeight="40" text="用戶名:" />
		<TextField fx:id="fieldUser" prefWidth="280" prefHeight="40" />
	</HBox>
	<HBox fx:id="hbPassword" prefWidth="400" prefHeight="40">
		<Label fx:id="labelPassword" prefWidth="120" prefHeight="40" text="密 碼:" />
		<PasswordField fx:id="fieldPassword" prefWidth="280" prefHeight="40" />
	</HBox>
	<Button fx:id="btnLogin" prefWidth="400" prefHeight="40" text="登  錄" />
</FlowPane>

在idea中打開login.fxml,注意到該文件界面的左下角有兩個選項卡,一個叫“Text”,另一個叫“Scene Builder”。當前打開的login.fxml展示為文本內容,對應的正是“Text”選項,此時單擊右邊的“Scene Builder”選項,原先的文本內容迅速變為一組可視化頁面,頁面中央呈現着login.fxml的預覽效果,正如下圖所示。

 

原來fxml文件類似於html文件,盡管html文件內部充斥着各種文本標簽,但使用瀏覽器打開html文件總能看到排版精美的網頁;而idea自帶的Scene Builder承擔了fxml瀏覽器的角色,只要程序員修改了fxml文件的格式內容,切換至“Scene Builder”選項就能立刻看見修改后的界面效果,比起傳統的運行程序看效果的方式,Scene Builder的渲染速度要快得多。
回頭再看前述的login.fxml,它的文件內容分為兩大塊,前面一塊形如“<?import ***?>”,其作用是導入指定包名路徑的控件,與Java代碼的import語句相似;后面一塊包含各級控件的嵌套結構,其標簽格式為“<控件名稱 屬性列表></控件名稱>”,如果當前控件不存在下級控件,則它的標簽格式可簡化為“<控件名稱 屬性列表 />”。依據login.fxml的標簽內容,可知該界面采取FlowPane流式窗格,且流式窗格擁有下列三類控件:
1、容納用戶名組件的水平箱子HBox,它的編號是hbUser。該箱子內部又有編號為labelUser的用戶名標簽,以及編號為fieldUser的用戶名輸入框;
2、容納密碼組件的水平箱子HBox,它的標識為hbPassword。該箱子內部又有編號為labelPassword的密碼標簽,以及編號為fieldPassword的密碼輸入框;
3、編號為btnLogin的登錄按鈕;
引入FXML布局之后,Java代碼要改為從指定的fxml文件中加載界面,也就是將場景的創建過程改成如下兩行代碼:

		// 從FXML資源文件中加載程序的初始界面
		Parent root = FXMLLoader.load(getClass().getResource("login.fxml"));
		Scene scene = new Scene(root, 410, 240); // 創建一個場景

 

於是繪制界面的JavaFX代碼縮小到了下面寥寥幾行:

//登錄窗口的程序入口(FXML布局控件)
public class LoginMain extends Application {

	@Override
	public void start(Stage stage) throws Exception { // 應用程序開始運行
		stage.setTitle("登錄窗口"); // 設置舞台的標題
		// 從FXML資源文件中加載程序的初始界面
		Parent root = FXMLLoader.load(getClass().getResource("login.fxml"));
		Scene scene = new Scene(root, 410, 240); // 創建一個場景
		stage.setScene(scene); // 設置舞台的場景
		stage.setResizable(true); // 設置舞台的尺寸是否允許變化
		stage.show(); // 顯示舞台
	}

	public static void main(String[] args) {
		launch(args); // 啟動JavaFX應用,接下來會跳到start方法
	}
}

接着運行上面的LoginMain程序,彈出的登錄界面正如預期所示。

JavaFX的絕大多數靜態控件,都能以單個標簽的形式添加到fxml之中,除了前面例子提及的流式窗格FlowPane、水平箱子HBox、按鈕Button、標簽Label、文本輸入框TextField、密碼輸入框PasswordField,還包括網格窗格GridPane、邊界窗格BorderPane、垂直箱子VBox、多行輸入框TextArea、復選框CheckBox、下拉框ComboBox等。然而單選按鈕RadioButton的添加方式別具一格,緣由在於好幾個單選按鈕要構成一個按鈕小組,這樣才能讓同組的單選按鈕聯動起來。因此fxml得先聲明一個ToggleGroup標簽,並給它分配標簽編號,然后在RadioButton標簽后面添加toggleGroup屬性,指定加入前一步的ToggleGroup編號。操作單選按鈕的具體fxml片段示例如下:

	<HBox fx:id="hbType" prefWidth="400" prefHeight="40">
		<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="驗證碼登錄" />
	</HBox>

 

當然,新來的RadioButton和ToggleGroup也要在fxml頭部添加以下的導入語句:

<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.ToggleGroup?>

 

把與單選按鈕有關的xml標簽補充到login.fxml,再另存為新的fxml文件名叫login_with_flow.fxml,完整的文件內容如下所示:

<?import javafx.scene.layout.FlowPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.ToggleGroup?>

<FlowPane xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="5" vgap="5">
	<HBox fx:id="hbType" prefWidth="400" prefHeight="40">
		<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="驗證碼登錄" />
	</HBox>
	<HBox fx:id="hbUser" prefWidth="400" prefHeight="40">
		<Label fx:id="labelUser" prefWidth="120" prefHeight="40" text="用戶名:" />
		<TextField fx:id="fieldUser" prefWidth="280" prefHeight="40" />
	</HBox>
	<HBox fx:id="hbPassword" prefWidth="400" prefHeight="40">
		<Label fx:id="labelPassword" prefWidth="120" prefHeight="40" text="密 碼:" />
		<PasswordField fx:id="fieldPassword" prefWidth="280" prefHeight="40" />
	</HBox>
	<Button fx:id="btnLogin" prefWidth="400" prefHeight="40" text="登  錄" />
	<Label fx:id="labelLoginResult" prefWidth="400" prefHeight="40" text="這里顯示登錄結果" />
</FlowPane>

然后利用Scene Builder觀察login_with_flow.fxml的預覽界面,由下圖可見單選按鈕組合已經添加至登錄窗口的上方。

 

接着修改LoginMain.java,將創建場景時加載的資源文件名改為login_with_flow.fxml,再重新運行測試程序,此時彈出的登錄界面如下圖所示:

 

比較Scene Builder的預覽界面,以及實際運行的窗口界面,總體而言兩者大同小異,基本的布局排列是吻合的。



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


免責聲明!

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



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