javafx 示例FXML

示例

一个简单的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方法执行多个操作,了解它们发生的顺序很有用。在这个简单的例子中:

  1. 在FXMLLoader读取并分析FXML文件。它创建与文件中定义的元素相对应的对象,并记下fx:id在其上定义的所有属性。

  2. 由于FXML文件的根元素定义了一个fx:controller属性,因此FXMLLoader会创建它指定的类的新实例。默认情况下,这是通过在指定的类上调用无参数构造函数来实现的。

  3. fx:id定义属性的任何元素在控制器中的字段具有匹配的字段名称,并且被public(不推荐)或带注释@FXML(推荐)的元素“注入”到那些对应的字段中。因此,在此示例中,由于LabelFXML文件中有fx:id="label"一个,并且控制器中的字段定义为

    @FXML
    private Label label ;

    该label字段将使用所Label创建的实例进行初始化FXMLLoader。

  4. 事件处理程序已在FXML文件中onXXX="#..."定义了属性的任何元素中注册。这些事件处理程序调用控制器类中的指定方法。在此示例中,由于ButtonhasonAction="#handleButtonAction"和控制器定义了一个方法

    @FXML
    private void handleButtonAction(ActionEvent event) { ... }

    当在按钮上触发动作时(例如,用户按下按钮),将调用此方法。该方法必须具有void返回类型,并且可以定义与事件类型匹配的参数(ActionEvent在此示例中),也可以不定义任何参数。

  5. 最后,如果控制器类定义了一个initialize方法,则将调用该方法。注意,这@FXML是在注入字段之后发生的,因此可以使用此方法安全地访问它们,并将使用与FXML文件中的元素相对应的实例进行初始化。该initialize()方法可以不带任何参数,也可以带aURL和a ResourceBundle。在后一种情况下,这些参数将由URL代表FXML文件的位置以及viaResourceBundle上的任何集合填充。如果未设置这些选项,则可以是任何一个。FXMLLoaderloader.setResources(...)null