一个简单的FXML文档,概述了一个AnchorPane包含按钮和标签节点的:
<?xml version="1.0" encoding="UTF-8"?> <?import java.lang.*?> <?import java.util.*?> <?import javafx.scene.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.FXMLDocumentController"> <children> <Button layoutX="126" layoutY="90" text="点击我!" onAction="#handleButtonAction" fx:id="button" /> <Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" /> </children> </AnchorPane>
此示例FXML文件与控制器类相关联。在这种情况下,通过指定类名称作为fx:controllerFXML的根元素中属性的值,可以在FXML和控制器类之间建立关联fx:controller="com.example.FXMLDocumentController"。控制器类允许执行Java代码,以响应用户对FXML文件中定义的UI元素的操作:
packagecom.example; import java.net.URL; import java.util.ResourceBundle; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Label; public class FXMLDocumentController { @FXML private Label label; @FXML private void handleButtonAction(ActionEvent event) { System.out.println("你点击了我!"); label.setText("你好,世界!"); } @Override public void initialize(URL url, ResourceBundle resources) { // 初始化代码可以在这里。 // 如果不需要,则可以省略参数url和resources } }
一个FXMLLoader可以被用于加载FXML文件:
public class MyApp extends Application { @Override public void start(Stage stage) throws Exception { FXMLLoader loader = new FXMLLoader(); loader.setLocation(getClass().getResource("FXMLDocument.fxml")); Parent root = loader.load(); Scene scene = new Scene(root); stage.setScene(scene); stage.show(); } }
该load方法执行多个操作,了解它们发生的顺序很有用。在这个简单的例子中:
在FXMLLoader读取并分析FXML文件。它创建与文件中定义的元素相对应的对象,并记下fx:id在其上定义的所有属性。
由于FXML文件的根元素定义了一个fx:controller属性,因此FXMLLoader会创建它指定的类的新实例。默认情况下,这是通过在指定的类上调用无参数构造函数来实现的。
fx:id定义属性的任何元素在控制器中的字段具有匹配的字段名称,并且被public(不推荐)或带注释@FXML(推荐)的元素“注入”到那些对应的字段中。因此,在此示例中,由于LabelFXML文件中有fx:id="label"一个,并且控制器中的字段定义为
@FXML
private Label label ;
该label字段将使用所Label创建的实例进行初始化FXMLLoader。
事件处理程序已在FXML文件中onXXX="#..."定义了属性的任何元素中注册。这些事件处理程序调用控制器类中的指定方法。在此示例中,由于ButtonhasonAction="#handleButtonAction"和控制器定义了一个方法
@FXML
private void handleButtonAction(ActionEvent event) { ... }
当在按钮上触发动作时(例如,用户按下按钮),将调用此方法。该方法必须具有void返回类型,并且可以定义与事件类型匹配的参数(ActionEvent在此示例中),也可以不定义任何参数。
最后,如果控制器类定义了一个initialize方法,则将调用该方法。注意,这@FXML是在注入字段之后发生的,因此可以使用此方法安全地访问它们,并将使用与FXML文件中的元素相对应的实例进行初始化。该initialize()方法可以不带任何参数,也可以带aURL和a ResourceBundle。在后一种情况下,这些参数将由URL代表FXML文件的位置以及viaResourceBundle上的任何集合填充。如果未设置这些选项,则可以是任何一个。FXMLLoaderloader.setResources(...)null