【问题标题】:FXML variable reference is nullFXML 变量引用为空
【发布时间】:2018-12-24 13:28:34
【问题描述】:

所以我正在学习如何使用 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 的变量,在我的第一个打印语句之后,我在productID 上得到一个运行时空指针异常

编辑: 上面的代码当前运行没有错误,但只会填充我表的“productID”部分。

【问题讨论】:

  • 在声明@FXML private TableView productTable 之后,如果我尝试从“productTable”调用任何方法,我也会得到一个空引用。

标签: java javafx nullpointerexception fxml fxmlloader


【解决方案1】:

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

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

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

假设您希望Application 扩展类成为控制器,您需要创建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&lt;Product, String&gt;("productID"));,您可能会收到NullPointerException,具体取决于您的代码顺序。

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

【讨论】:

  • 因此作为参考,我正在尝试将此代码 docs.oracle.com/javafx/2/ui_controls/table-view.htm# 调整为使用 FXML 表。在将您所说的内容移入我的控制器类后,我设法使其运行,但是我仍然只看到第一列被我的可观察列表填充,我将编辑上面的帖子以向您展示我的意思。
猜你喜欢
  • 1970-01-01
  • 2014-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多