JavaFX Scene Builder 與 FXML
|
Oracle為加速JavaFX圖形介面的開發,推出JavaFX Scene Builder,如同NetBeans或JBuilder IDE一般,藉由拖曳的方式配置物件,待完成配置之後,並儲存成FXML格式檔案,此檔案以XML描述物件配置,再交由JavaFX程式處理,因此可減少直接以JavaFX撰寫配置物件程式的困難度。 FXML類似於Java SE 5.0新增的Synth Look and Feel,其最大特色在於以XML描述物件配置與樣式,JavaFX程式在執行階段只需讀取此FXML檔案,則可設定JavaFX的物件配置,且配置或樣式改變,也僅需修改FXML檔案,不需修改JavaFX程式。JavaFX Scene Builder具有以下特色:
JavaFX Scene Builder可自Oracle網站下載。下載檔案名為javafx_scenebuilder-1_1-windows.msi的JavaFX Scene Builder之後,直接執行安裝程式即可完成安裝。 以JavaFX Scene Builder配置物件與建立FXML檔案的步驟如下: Step 1:執行JavaFX Scene Builder,其中JavaFX Scene Builder包含以下之區域:
下圖JavaFX Scene Builder的開始畫面: Step 2:點選「File」→「New」選單建立新檔,接著選擇物件如標籤,並拖曳至內容面板中,此時屬性面板將顯示標籤的所有屬性如標籤文字、字型、文字顏色、對齊方式等。接著依序以相同的方式拖曳物件至內容面板,此時階層面板將顯示所有物件的樹狀關係,其中最上層的容器為GridPane,如下圖所示: Step 3:待完成物件配置之後,點選「File」→「Save」選單儲存為FXML檔案,其內容如下所示: <?xml version="1.0" encoding="UTF-8"?> <?import java.lang.*?> <?import java.net.*?> <?import javafx.geometry.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <?import javafx.scene.text.*?> <GridPane alignment="CENTER" styleClass="root" hgap="10.0" vgap="10.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="javafxapplication.JavaFXController"> <padding> <Insets bottom="25.0" left="25.0" right="25.0" top="25.0" /> </padding> <Text id="welcome-text" text="Welcome to JavaFX" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="0" /> <Label text="User Name:" GridPane.columnIndex="0" GridPane.rowIndex="1" /> <TextField GridPane.columnIndex="1" GridPane.rowIndex="1" /> <Label text="Password:" GridPane.columnIndex="0" GridPane.rowIndex="2" /> <PasswordField fx:id="passwordField" GridPane.columnIndex="1" GridPane.rowIndex="2" /> <HBox alignment="BOTTOM_RIGHT" spacing="10.0" GridPane.columnIndex="1" GridPane.rowIndex="4"> <Button fx:id="button" text="Login" /> </HBox> </GridPane> 依照以上的步驟則完成以JavaFX Scene Builder配置物件與建立FXML檔案,上述FXML內容對應於以下的JavaFX程式:
import javafx.geometry.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.text.*;
...
GridPane gridpane = new GridPane();
gridpane.setAlignment(Pos.CENTER);
gridpane.setHgap(10);
gridpane.setVgap(10);
gridpane.setPadding(new Insets(25, 25, 25, 25));
Text text = new Text("Welcome to JavaFX");
text.setId("welcome-text");
gridpane.add(text, 0, 0, 2, 0);
gridpane.add(new Label("User Name:"), 0, 1);
gridpane.add(new TextField(), 1, 1);
gridpane.add(new Label("Password:"), 0, 2);
PasswordField passwordfield = new PasswordField();
passwordfield.setId("passwordField");
gridpane.add(passwordfield, 1, 2);
Button button = new Button("Login");
button.setId("button");
HBox hbox = new HBox();
hbox.setAlignment(Pos.BOTTOM_RIGHT);
hbox.setSpacing(10);
hbox.getChildren().add(button);
gridpane.add(hbox, 1, 4);
...
接著將FXML檔案與JavaFX程式置於同一目錄,並以javafx.fxml.FXMLLoader類別的load()方法將FXML檔案的內容載入至JavaFX程式中,由於在JavaFX Scene Builder中設定最上層的容器為GridPane類別,因此載入FXML內容之後,需轉換為GridPane: try {
// 載入FXML內容並轉換為GridPane
GridPane fxmlRoot = (GridPane) FXMLLoader.load(
getClass().getResource("JavaFXApplication.fxml"));
Scene scene = new Scene(fxmlRoot);
primaryStage.setTitle("JavaFX Hello World");
primaryStage.setScene(scene);
// Show Stage
primaryStage.show();
}
catch (IOException ex) {
System.out.println(ex.toString());
}
...
為避免因變更最上層容器而需要修改原JavaFX程式,因此亦可將載入FXML內容轉換為Parent抽象類別,如此不論最上層容器為何,均不需修改JavaFX程式: try {
// 載入FXML內容並轉換為Parent
Parent fxmlRoot = FXMLLoader.load(
getClass().getResource("JavaFXApplication.fxml"));
Scene scene = new Scene(fxmlRoot);
primaryStage.setTitle("JavaFX Hello World");
primaryStage.setScene(scene);
// Show Stage
primaryStage.show();
}
catch (IOException ex) {
System.out.println(ex.toString());
}
...
由於FXML已處理所有的物件配置,因此JavaFX程式變得更為精簡。此外,FXML可搭配事件處理,首先建立一處理事件的Controller類別,並將此Controller類別與FXML檔案置於同一目錄,例如: package javafxapplication;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
/**
* Controller class
*/
public class JavaFXController implements Initializable {
@FXML
Button button;
/**
* Initializes the controller class.
*/
@Override
public void initialize(URL location, ResourceBundle resources) {
if (button != null) {
button.setOnAction(new EventHandler() {
@Override public void handle(ActionEvent e) {
System.out.println("Hello World");
}
});
}
}
}
接著在JavaFX Scene Builder的屬性面板中,設定最上層容器的Controller類別為上述自定之類別,當點選物件如按鈕時,則以此自定的Controller類別處理物件的事件,如下圖所示: 【執行結果】 除了處理事件的Controller類別之外,FXML支援CSS設定物件樣式,首先將CSS樣式定義於CSS檔案中,並將此CSS檔案與FXML檔案置於同一目錄,例如: .background {
-fx-background-image: url("images/javafx.jpg");
-fx-background-repeat: repeat;
-fx-background-color:
linear-gradient(#38424b 0%, #1f2429 20%, #191d22 100%),
linear-gradient(#20262b, #191d22),
radial-gradient(center 50% 0%, radius 100%,
rgba(114,131,148,0.9), rgba(255,255,255,0));
}
.top-segment {
-fx-background-color: rgba(255, 255, 255, 0.05);
-fx-border-color:
transparent transparent rgb(255, 255, 255, 0.08) transparent,
transparent transparent rgb(0, 0, 0, 0.5) transparent;
-fx-border-width: 1, 1.5;
-fx-border-insets: -1, 0;
}
.title {
-fx-font-size: 16;
}
.label {
-fx-font-family: "Verdana";
-fx-font-size: 12;
-fx-text-fill: rgb(162, 21, 35, 1);
-fx-effect: dropshadow(one-pass-box ,
rgb(0, 0, 0, 0.6), 0, 0, 0, 1);
}
.button .text {
-fx-effect: dropshadow(one-pass-box,
rgb(0, 0, 0, 0.8), 0, 0, 0, -1);
}
.button {
-fx-background-color:
rgb(255, 255, 255, 0.08), rgb(0, 0, 0, 0.8), #090a0c,
linear-gradient(#4a5661 0%, #1f2429 20%, #1f242a 100%),
linear-gradient(#242a2e, #23282e),
radial-gradient(center 50% 0%, radius 100%,
rgba(135,142,148,0.9), rgba(255,255,255,0));
-fx-background-radius: 7, 6, 5, 4, 3, 5;
-fx-background-insets: -3 -3 -4 -3, -3, 0, 1, 2, 0;
-fx-font-family: "Verdana";
-fx-text-fill: blue;
-fx-text-fill: linear-gradient(white, #d0d0d0);
-fx-padding: 10 20 10 20;
}
.button:focused, .button:hover {
-fx-background-color:
rgb(255, 255, 255, 0.08),
rgb(0, 0, 0, 0.8), #090a0c,
linear-gradient(#4a5661 0%, #1f2429 20%, #1f242a 100%),
linear-gradient(#3f4950, #23282e),
radial-gradient(center 50% 0%, radius 100%,
rgba(135,142,148,0.9), rgba(255,255,255,0));
}
.text-field {
-fx-background-color:
rgb(255, 255, 255, 0.3),
linear-gradient(rgb(0, 0, 0, 0.5), rgb(0, 0, 0, 0.8) 50%),
rgb(218, 226, 224);
-fx-background-insets: 0 0 -1 0, 0, 1.5;
-fx-background-radius: 6, 5, 4;
-fx-padding: 6 10 4 10;
-fx-effect: innershadow(gaussian, rgb(0, 0, 0, 0.8), 5, 0, 0, 2 );
-fx-font-family: "Verdana";
}
.text-field:focused {
-fx-prompt-text-fill: rgb(128,128,128);
-fx-background-color: rgb(235, 235, 235, 0.5),
rgb(0, 0, 0, 0.4), rgb(255, 255, 255);
}
接著在JavaFX Scene Builder的屬性面板中,設定最上層容器GridPane的Stylesheets為上述之CSS檔案,並設定GridPane的Style Class為CSS檔案中所定義的background,如下圖所示: 以此類推,依序點選各物件並設定其Style Class,如此則完成以CSS設定物件樣式,其中JavaFX程式完全不需任何修改。 【執行結果】 【參考資料】 [1] Java Official Web Site |

Java 學習之路






