初始化期间的 Nullpointer 异常/FXML 注入未按预期工作
Nullpointer Exception during initialize / FXML injection not working as expected
我注意到我的一个控制器有一个奇怪的行为 类。组件之一未初始化。
这是 fxml:
<?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="500.0" prefWidth="712.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="modulartoolkit.ConfigWindowController">
<children>
<Label layoutX="14.0" layoutY="12.0" text="Processes:" />
<Button fx:id="newProcessButton" layoutX="324.0" layoutY="82.0" mnemonicParsing="false" onAction="#handleNewProcessButtonAction" prefHeight="25.0" prefWidth="51.0" text="New" />
<Button fx:id="editProcessButton" layoutX="324.0" layoutY="118.0" mnemonicParsing="false" onAction="#handleEditProcessButtonAction" prefHeight="25.0" prefWidth="51.0" text="Edit" />
<Button fx:id="deleteProcessButton" layoutX="324.0" layoutY="154.0" mnemonicParsing="false" onAction="#handleDeleteProcessButtonAction" text="Delete" />
<ListView fx:id="processListView" layoutX="14.0" layoutY="30.0" prefHeight="200.0" prefWidth="295.0" />
<Label layoutX="14.0" layoutY="250.0" text="Available Modules:" />
<Label layoutX="400.0" layoutY="250.0" text="Configured Modules:" />
<ListView layoutX="397.0" layoutY="266.0" prefHeight="200.0" prefWidth="295.0" />
<TreeView layoutX="14.0" layoutY="266.0" prefHeight="200.0" prefWidth="295.0" />
</children>
</AnchorPane>
这就是控制器:
public class ConfigWindowController implements Initializable {
private Database database;
private final ObservableList processListData = FXCollections.observableArrayList();
@FXML
private Button newProcessButton;
private Button editProcessButton;
private Button deleteProcessButton;
private ListView<String> processListView;
/**
* Initializes the controller class.
*
* @param url
* @param rb
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
this.database = Database.getInstance();
processListView.setItems(processListData);
}
@FXML
private void handleNewProcessButtonAction(ActionEvent event) {
System.out.println("new Process");
}
@FXML
private void handleEditProcessButtonAction(ActionEvent event) {
System.out.println("EDIT!");
}
@FXML
private void handleDeleteProcessButtonAction(ActionEvent event) {
System.out.println("DELETE!");
}
}
启动应用程序后,我得到一个 NullPointerException
,因为 ListView
为空。
我可以通过向 ListView
:
添加 @FXML 注释来修复它
@FXML
private Button newProcessButton;
private Button editProcessButton;
private Button deleteProcessButton;
@FXML
private ListView<String> processListView;
如果我将 ListView
移动到声明的顶部,它也会起作用。在每种情况下,所有按钮都会被初始化。
有人知道为什么会这样吗?我认为注释只需要在声明的开头。还是必须为每种类型的组件输入?
其实最后两个按钮没有启动,所以肯定是null
。然而,在 fxml 文件中定义的按钮被实例化,并且具有 onAction
属性设置为在控制器 class 中定义的那些也有 @FXML 注释。因此,单击这些按钮将起作用并按预期触发事件操作处理程序。
@FXML 注释使 FXMLLoader 有义务实例化带注释的节点,并将其 link 到具有相应 fx:id
的 fxml 文件中定义的节点。因此,如果该节点未使用 @FXML 注释且未显式启动,则它为空。这就是注释在 Java 语言中的工作方式。您可以通过检查最后两个按钮是否为空来确认这一点。
因此,每个 control/node 都应单独注释:
@FXML
private Button newProcessButton;
@FXML
private Button editProcessButton;
@FXML
private ListView<String> processListView;
或像这样组合:
@FXML
private Button newProcessButton, editProcessButton;
@FXML
private ListView<String> processListView;
我注意到我的一个控制器有一个奇怪的行为 类。组件之一未初始化。
这是 fxml:
<?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="500.0" prefWidth="712.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="modulartoolkit.ConfigWindowController">
<children>
<Label layoutX="14.0" layoutY="12.0" text="Processes:" />
<Button fx:id="newProcessButton" layoutX="324.0" layoutY="82.0" mnemonicParsing="false" onAction="#handleNewProcessButtonAction" prefHeight="25.0" prefWidth="51.0" text="New" />
<Button fx:id="editProcessButton" layoutX="324.0" layoutY="118.0" mnemonicParsing="false" onAction="#handleEditProcessButtonAction" prefHeight="25.0" prefWidth="51.0" text="Edit" />
<Button fx:id="deleteProcessButton" layoutX="324.0" layoutY="154.0" mnemonicParsing="false" onAction="#handleDeleteProcessButtonAction" text="Delete" />
<ListView fx:id="processListView" layoutX="14.0" layoutY="30.0" prefHeight="200.0" prefWidth="295.0" />
<Label layoutX="14.0" layoutY="250.0" text="Available Modules:" />
<Label layoutX="400.0" layoutY="250.0" text="Configured Modules:" />
<ListView layoutX="397.0" layoutY="266.0" prefHeight="200.0" prefWidth="295.0" />
<TreeView layoutX="14.0" layoutY="266.0" prefHeight="200.0" prefWidth="295.0" />
</children>
</AnchorPane>
这就是控制器:
public class ConfigWindowController implements Initializable {
private Database database;
private final ObservableList processListData = FXCollections.observableArrayList();
@FXML
private Button newProcessButton;
private Button editProcessButton;
private Button deleteProcessButton;
private ListView<String> processListView;
/**
* Initializes the controller class.
*
* @param url
* @param rb
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
this.database = Database.getInstance();
processListView.setItems(processListData);
}
@FXML
private void handleNewProcessButtonAction(ActionEvent event) {
System.out.println("new Process");
}
@FXML
private void handleEditProcessButtonAction(ActionEvent event) {
System.out.println("EDIT!");
}
@FXML
private void handleDeleteProcessButtonAction(ActionEvent event) {
System.out.println("DELETE!");
}
}
启动应用程序后,我得到一个 NullPointerException
,因为 ListView
为空。
我可以通过向 ListView
:
@FXML
private Button newProcessButton;
private Button editProcessButton;
private Button deleteProcessButton;
@FXML
private ListView<String> processListView;
如果我将 ListView
移动到声明的顶部,它也会起作用。在每种情况下,所有按钮都会被初始化。
有人知道为什么会这样吗?我认为注释只需要在声明的开头。还是必须为每种类型的组件输入?
其实最后两个按钮没有启动,所以肯定是null
。然而,在 fxml 文件中定义的按钮被实例化,并且具有 onAction
属性设置为在控制器 class 中定义的那些也有 @FXML 注释。因此,单击这些按钮将起作用并按预期触发事件操作处理程序。
@FXML 注释使 FXMLLoader 有义务实例化带注释的节点,并将其 link 到具有相应 fx:id
的 fxml 文件中定义的节点。因此,如果该节点未使用 @FXML 注释且未显式启动,则它为空。这就是注释在 Java 语言中的工作方式。您可以通过检查最后两个按钮是否为空来确认这一点。
因此,每个 control/node 都应单独注释:
@FXML
private Button newProcessButton;
@FXML
private Button editProcessButton;
@FXML
private ListView<String> processListView;
或像这样组合:
@FXML
private Button newProcessButton, editProcessButton;
@FXML
private ListView<String> processListView;