除了使用Java原生的Code產生圖形介面外,JavaFX還支援使用XML來描述圖形介面(這好像已經成為一種趨勢了)。甚至Oracle還提供了一種叫作JavaFX Scene Builder的工具,讓開發人員製作圖形介面完全不用寫到程式。
JavaFX Scene Builder
JavaFX Scene Builder可以到Oracle的網站上下載安裝,之後就可以拿來排介面了!
拿之前登入表單的例子,使用JavaFX Scene Builder花不到五分鐘就可以做好下面的介面!之後存檔成fxml檔案就可以套入在JavaFX內啦!
使用FXML開發JavaFX的專案要注意到,若程式需要存取到圖形元件的狀態,需設定ID欄位,這樣才可以使用node的lookup
或是lookupAll
方法,以CSS名稱(#ID名稱)的字串方式,來找出該node底下符合此ID名稱的sub node。如果圖形元件需要處理事件,可以設定onAction
欄位,由FXML去指向事件觸發後要執行的方法名稱,但此方法需要用到@FXML
這個annotation來實作。另外,@FXML
也可以抓到FXML元件的fxID。要使用@FXML annotation的話,必須要替FXML指定Controller(指到JavaFX應用程式內的某個類別)。
套入FXML
JavaFX提供FXMLLoader.load()
方法,可以將FXML讀入,並轉換成Node。
撰寫程式
LoginJavaFX.java
package javafxlogin;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class LoginJavaFX extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
Parent root = FXMLLoader.load(getClass().getResource("Login.fxml"));
//用讀進來FXML的作為Scene的root node
Scene scene = new Scene(root, 300, 275);
primaryStage.setScene(scene);
//顯示Stage
primaryStage.setTitle("登入");
primaryStage.show();
}
}
FXController.java
package javafxlogin;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.text.Text;
public class FXController {
@FXML
private Text actiontarget;
@FXML
protected void submit(ActionEvent event) {
actiontarget.setText("登入成功");
}
}
Login.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<GridPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="275.0" prefWidth="300.0" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxlogin.FXController">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
</rowConstraints>
<children>
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="歡迎">
<font>
<Font size="20.0"/>
</font>
</Text>
<Label text="帳號:" GridPane.rowIndex="1"/>
<TextField GridPane.columnIndex="1" GridPane.rowIndex="1"/>
<Label text="密碼:" GridPane.rowIndex="2"/>
<PasswordField GridPane.columnIndex="1" GridPane.rowIndex="2"/>
<HBox alignment="BOTTOM_RIGHT" prefHeight="100.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="4">
<children>
<Button mnemonicParsing="false" onAction="#submit" text="登入"/>
</children>
</HBox>
<Text fx:id="actiontarget" id="actiontarget" fill="#ff4529" strokeType="OUTSIDE" strokeWidth="0.0" GridPane.columnIndex="1" GridPane.rowIndex="6"/>
</children>
<padding>
<Insets bottom="25.0" left="25.0" right="25.0" top="25.0"/>
</padding>
</GridPane>
執行結果: