FXML 变量引用为空

FXML variable reference is null

所以我正在学习如何使用 FXML,我 运行 遇到了另一个问题,即 fx:id 在 运行 时间获取对对象的引用,我得到了空指针异常,代码如下。

  <TableView fx:id="productTable" layoutX="92.0" layoutY="319.0" prefHeight="97.0" prefWidth="363.0" GridPane.columnIndex="7" GridPane.columnSpan="5" GridPane.rowIndex="3" GridPane.rowSpan="2">
     <columns>
        <TableColumn prefWidth="98.0" text="Product ID" fx:id="productID"/>
        <TableColumn prefWidth="110.0" text="Product Name" fx:id="productName"/>
        <TableColumn prefWidth="131.0" text="Inventory Level" fx:id="productInventoryLevel"/>
        <TableColumn prefWidth="128.0" text="Price per Unit" fx:id="productPrice"/>
     </columns>
  </TableView>
//Controller.java
@FXML private TableView<Product> productTable;
@FXML private TableColumn<Product, String> productID;
@FXML private TableColumn<Product, String>  productPrice;
@FXML private TableColumn<Product, String>  productName;
@FXML private TableColumn<Product, String>  productInventoryLevel;

//Product properties declared the same as https://docs.oracle.com/javafx/2/ui_controls/table-view.htm#
private ObservableList<Product> productData = FXCollections.observableArrayList(
        new Product(0, "Wheel", 100.99, 4, 0, 1), 
        new Product(1, "Seat", 50.0, 4, 0, 1));

@Override
public void initialize(URL url, ResourceBundle rb) {
    // TODO
    System.out.println("Product ID factories");

    productID.setCellValueFactory(new PropertyValueFactory<Product, String>("productID"));
    productPrice.setCellValueFactory(new PropertyValueFactory<Product, String>("productPrice"));
    productInventoryLevel.setCellValueFactory(new PropertyValueFactory<Product, String>("productInventoryLevel"));
    productName.setCellValueFactory(new PropertyValueFactory<Product, String>("productName"));
     productTable.setItems(productData);

      System.out.println("Set items");

}    

如您所见,我声明了 @FXML 标记,然后通过 fx:id 声明了变量,在我的第一个打印语句之后,我在 [= 上得到了一个 运行time 空指针异常14=]

编辑: 上面的代码目前 运行s 没有错误,但只会填充我的 table 的 "productID" 部分。

首先,不确定 UI class 扩展了什么。它看起来确实是从 Application 扩展而来的,并且是整个应用程序的起始 class。

根据我的最佳猜测,我会说您这样做有两个可能的原因:

  1. 您从第一个(Application 扩展)class 复制而来。这不太可能,因为你说你有一个 NullPointerException,除非你手动调用 start().
  2. 这个"controller"class确实是起始class,你打算让它成为控制器class对于 FXMLDocument.fxml。这似乎是这里可能的情况。

假设你想让Application扩展class成为一个控制器,你需要创建一个FXMLLoader的实例,而不是使用静态方法FXMLLoader.load() .

FXMLLoader loader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));
loader.setController(this); // You need to set this instance as the controller.
Parent root = loader.load();
// Other stuff you need to do
productID.setCellValueFactory(new PropertyValueFactory<Product, String>("productID"));

这会将 UI 的当前 运行 实例设置为 FXMLDocument.fxml 的控制器。

有几点需要注意。

  1. 不要在 FXML 中使用 fx:controller,或者创建 UI 的新实例(并设置它)作为替代。您必须将当前实例提供给FXMLLoader
  2. 通过 @FXML 注释的所有字段将仅在调用 FXMLLoader.load() 之后或在 initialize() 方法中注入(即非空)。如果您尝试调用 productID.setCellValueFactory(new PropertyValueFactory<Product, String>("productID"));,您可能会得到一个 NullPointerException,具体取决于您的代码顺序。

最后,您可以选择让另一个 class FXML 文件的控制器。事实上,大多数人会这样做,因为这是 MVC 的目的(这是 JavaFX 使用的架构)。当然,所有注入的字段和初始化也会移动到新的控制器class。还请记住,注入字段在构造函数中是 null - 因此在新控制器 class.

initialize() 中初始化