所以我正在学习如何使用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
上获得了运行时nullpointer异常
编辑: 上面的代码当前可以正常运行,但只会填充表的“ productID”部分。
答案 0 :(得分:0)
首先,不确定UI
类的扩展范围。它确实看起来像是从Application
扩展而来的,并且是整个应用程序的起始类。
尽我最大的猜测,我会说您这样做有两个可能的原因:
Application
扩展)类复制的。这是不可能的,因为您说过自己有一个NullPointerException
,除非您手动调用了start()
。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
的控制器。
有几点需要注意。
fx:controller
,也不要创建UI
的新实例(并进行设置)。您必须将当前实例提供给FXMLLoader
。@FXML
注释的字段仅在调用FXMLLoader.load()
后或以initialize()
方法被注入(即非空)。如果您尝试致电productID.setCellValueFactory(new PropertyValueFactory<Product, String>("productID"));
,则可能会收到NullPointerException
,具体取决于代码的顺序。最后,您确实可以选择使另一个类成为FXML文件的控制器。实际上,大多数人会这样做,因为那是MVC(JavaFX使用的体系结构)的目的。当然,所有注入的字段和初始化也将移至新的控制器类。还请记住,注入的字段是构造函数中的null
-因此请在新控制器类的initialize()
中进行初始化。