5.7.4 FXML
有些JavaFX程序的界面比较复杂,包含非常多的元素。创建这类界面的代码非常繁琐,可读性差,也很难进行维护。JavaFX允许开发人员使用FXML语言来描述程序的界面。FXML使用的是XML的语法。可以从FXML文档中创建出用户界面。使用FXML的好处是界面上组件之间的层次结构非常清晰,易于更新和维护。不熟悉Java的界面设计人员也可以用FXML来描述界面。
在JavaFX程序中,使用FXML有三个步骤。第一步是使用FXML的语法格式来描述程序的用户界面;第二步是通过javafx.fxml.FXMLLoader类加载一个FXML文档,并得到相应的用户界面的对象;第三步是在JavaFX程序中直接使用得到的组件对象。
FXML的基本语法比较简单。FXML中的元素可以表示对象实例、属性或代码块。对于对象实例,元素的名称是对应的Java类的名称,而元素的属性用来设置对象的属性值。对象的某些属性比较复杂,不能用简单的XML属性来描述,只能用子元素来表示。代码清单5-20给出了一个用FXML描述JavaFX程序界面的示例。处理指令“import”类似Java中的import语句。FXML文档中的元素“<VBox>”、“<HBox>”、“<Button>”和“<Label>”等用来创建对应的对象。简单的属性,如VBox类的spacing,可以直接在XML元素的属性上设置;复杂的属性,如VBox类的对象所包含的子组件children,可以通过子元素来设置。
代码清单5-20 使用FXML描述JavaFX程序界面的示例
<?xml version="1.0"encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.*?>
<?import javafx.collections.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<VBox id="main"spacing="20"prefHeight="300"prefWidth="400"xmlns:fx="http://javafx.com/fxml"fx:controller="javafx.fxml.Form">
<children>
<HBox spacing="10">
<children>
<Label text="Name:"/>
<TextField fx:id="name"promptText="Enter your name"/>
</children>
</HBox>
<HBox spacing="10">
<children>
<Label text="Gender:"/>
<ListView fx:id="gender">
<items>
<FXCollections fx:factory="observableArrayList">
<String fx:value="Male"/>
<String fx:value="Female"/>
</FXCollections>
</items>
</ListView>
</children>
</HBox>
<HBox>
<children>
<Button id="button"text="Say"onAction="#say"fx:id="button"/>
<Label id="message"fx:id="message"/>
</children>
</HBox>
</children>
</VBox>
每个FXML文档可以与一个Java对象关联起来,这个Java对象被称为FXML文档的控制器。通过FXML文档根元素的“fx:controller”属性来声明控制器的Java类名。在FXML文档中可以引用控制器对象中的方法。具体的格式是在方法名称上加上“#”作为前缀。代码清单5-20中的“<Button>”元素的“onAction”属性引用了控制器对象中的“say”方法。
创建出FXML文档之后,可以在JavaFX程序中通过FXMLLoader类来使用它。代码清单5-21给出了相关的示例。FXMLLoader类的load方法可以从不同的来源加载FXML文档,并创建出FXML文档中声明的组件对象。这个创建出来的组件对象可以在JavaFX程序中自由使用。
代码清单5-21 在JavaFX程序中加载FXML文档的示例
public class JavafxFxml extends Application{
public static void main(String[]args){
launch(args);
}
public void start(Stage stage)throws Exception{
Parent root=FXMLLoader.load(getClass().getResource("Form.fxml"));
stage.setScene(new Scene(root));
stage.show();
}
}