JavaFX在尝试用项目填充TextView时引发空指针异常
我正在尝试为学校创建一个简单的JavaFX项目,让用户玩游戏Nim。在我看来,这个概念很简单,因为我以前已经使用过java和JavaFX。当我试图通过传入一个可观察列表来设置TableView中的项时,会发生此错误。我确信列表中包含我应该能够添加的对象。我不知道怎么了 以下是我的全部代码: 主控制器类:JavaFX在尝试用项目填充TextView时引发空指针异常,java,javafx,Java,Javafx,我正在尝试为学校创建一个简单的JavaFX项目,让用户玩游戏Nim。在我看来,这个概念很简单,因为我以前已经使用过java和JavaFX。当我试图通过传入一个可观察列表来设置TableView中的项时,会发生此错误。我确信列表中包含我应该能够添加的对象。我不知道怎么了 以下是我的全部代码: 主控制器类: package controllers; import format.FormatStringValueForTableView; import javafx.event.ActionEven
package controllers;
import format.FormatStringValueForTableView;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import java.io.IOException;
import java.util.Random;
public class MainController {
@FXML private TextField inputTextField;
private final FormatStringValueForTableView formatter = new FormatStringValueForTableView();
@FXML
private void continueToGame(ActionEvent event) throws IOException {
FXMLLoader parent = new FXMLLoader(getClass().getClassLoader().getResource("ui/nim_game.fxml"));
Parent root = parent.load();
NimGameController nimGameController = parent.getController();
nimGameController.setList(formatter.formatString(inputTextField.getText()));
Scene scene = new Scene(root);
Stage appStage = (Stage) ((Node) event.getSource()).getScene().getWindow();
appStage.setScene(scene);
appStage.show();
}
@FXML
private void generateRandomNumber(ActionEvent event){
Random random = new Random();
int generatedNumber = random.nextInt(999) + 22;
inputTextField.setText(Integer.toString(generatedNumber));
}
}
package controllers;
import entities.Node;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;
public class NimGameController implements Initializable {
private ObservableList<Node> textInTextFieldToList;
@FXML private TableView<Node> tableView;
public void setList(ObservableList<Node> textInTextFieldToList) {
this.textInTextFieldToList = textInTextFieldToList;
}
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
configureTable();
populateTable();
}
@FXML
private void showNumsForDebug(ActionEvent event) {
textInTextFieldToList.forEach(System.out::println);
}
@FXML
private void back(ActionEvent event) throws IOException {
Parent parent = FXMLLoader.load(getClass().getClassLoader().getResource("ui/main.fxml"));
Scene scene = new Scene(parent);
Stage appStage = (Stage) ((javafx.scene.Node) event.getSource()).getScene().getWindow();
appStage.setScene(scene);
appStage.show();
}
private void configureTable() {
TableColumn<Node, Integer> itemColumn = new TableColumn<>("Item");
itemColumn.prefWidthProperty().bind(tableView.widthProperty().multiply(0.3));
itemColumn.setCellValueFactory(new PropertyValueFactory<>("value"));
itemColumn.setResizable(false);
TableColumn<Node, Integer> levelColumn = new TableColumn<>("Level");
levelColumn.prefWidthProperty().bind(tableView.widthProperty().multiply(0.3));
levelColumn.setCellValueFactory(new PropertyValueFactory<>("level"));
levelColumn.setResizable(false);
TableColumn<Node, Integer> functionValColumn = new TableColumn<>("Func. Val.");
functionValColumn.prefWidthProperty().bind(tableView.widthProperty().multiply(0.4));
functionValColumn.setCellValueFactory(new PropertyValueFactory<>("functionValue"));
functionValColumn.setResizable(false);
tableView.getColumns().add(itemColumn);
tableView.getColumns().add(levelColumn);
tableView.getColumns().add(functionValColumn);
}
public void populateTable(){
if(!textInTextFieldToList.isEmpty()){
tableView.setItems(textInTextFieldToList);
} else {
System.out.println("List is empty");
}
}
}
NimGameController类:
package controllers;
import format.FormatStringValueForTableView;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import java.io.IOException;
import java.util.Random;
public class MainController {
@FXML private TextField inputTextField;
private final FormatStringValueForTableView formatter = new FormatStringValueForTableView();
@FXML
private void continueToGame(ActionEvent event) throws IOException {
FXMLLoader parent = new FXMLLoader(getClass().getClassLoader().getResource("ui/nim_game.fxml"));
Parent root = parent.load();
NimGameController nimGameController = parent.getController();
nimGameController.setList(formatter.formatString(inputTextField.getText()));
Scene scene = new Scene(root);
Stage appStage = (Stage) ((Node) event.getSource()).getScene().getWindow();
appStage.setScene(scene);
appStage.show();
}
@FXML
private void generateRandomNumber(ActionEvent event){
Random random = new Random();
int generatedNumber = random.nextInt(999) + 22;
inputTextField.setText(Integer.toString(generatedNumber));
}
}
package controllers;
import entities.Node;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;
public class NimGameController implements Initializable {
private ObservableList<Node> textInTextFieldToList;
@FXML private TableView<Node> tableView;
public void setList(ObservableList<Node> textInTextFieldToList) {
this.textInTextFieldToList = textInTextFieldToList;
}
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
configureTable();
populateTable();
}
@FXML
private void showNumsForDebug(ActionEvent event) {
textInTextFieldToList.forEach(System.out::println);
}
@FXML
private void back(ActionEvent event) throws IOException {
Parent parent = FXMLLoader.load(getClass().getClassLoader().getResource("ui/main.fxml"));
Scene scene = new Scene(parent);
Stage appStage = (Stage) ((javafx.scene.Node) event.getSource()).getScene().getWindow();
appStage.setScene(scene);
appStage.show();
}
private void configureTable() {
TableColumn<Node, Integer> itemColumn = new TableColumn<>("Item");
itemColumn.prefWidthProperty().bind(tableView.widthProperty().multiply(0.3));
itemColumn.setCellValueFactory(new PropertyValueFactory<>("value"));
itemColumn.setResizable(false);
TableColumn<Node, Integer> levelColumn = new TableColumn<>("Level");
levelColumn.prefWidthProperty().bind(tableView.widthProperty().multiply(0.3));
levelColumn.setCellValueFactory(new PropertyValueFactory<>("level"));
levelColumn.setResizable(false);
TableColumn<Node, Integer> functionValColumn = new TableColumn<>("Func. Val.");
functionValColumn.prefWidthProperty().bind(tableView.widthProperty().multiply(0.4));
functionValColumn.setCellValueFactory(new PropertyValueFactory<>("functionValue"));
functionValColumn.setResizable(false);
tableView.getColumns().add(itemColumn);
tableView.getColumns().add(levelColumn);
tableView.getColumns().add(functionValColumn);
}
public void populateTable(){
if(!textInTextFieldToList.isEmpty()){
tableView.setItems(textInTextFieldToList);
} else {
System.out.println("List is empty");
}
}
}
main.fxml文件:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<GridPane alignment="center" hgap="10" maxHeight="300.0" maxWidth="500.0" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0" prefWidth="431.0" vgap="10" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.MainController">
<children>
<AnchorPane maxHeight="300.0" maxWidth="500.0" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0" prefWidth="400.0">
<children>
<SplitPane dividerPositions="0.17676767676767677" orientation="VERTICAL" prefHeight="200.0" prefWidth="400.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
<children>
<Label alignment="CENTER" layoutX="80.0" layoutY="-2.0" prefHeight="40.0" prefWidth="238.0" text="Welcome to NIM game." underline="true">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Label>
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="341.0">
<children>
<Label layoutX="49.0" layoutY="14.0" prefHeight="30.0" prefWidth="300.0" text="Enter a string of numbers that will be split: ">
<font>
<Font size="15.0" />
</font></Label>
<TextField fx:id="inputTextField" layoutX="49.0" layoutY="54.0" prefHeight="25.0" prefWidth="300.0" />
<Button layoutX="47.0" layoutY="104.0" mnemonicParsing="false" onAction="#continueToGame" prefHeight="32.0" prefWidth="102.0" text="Continue" />
<Button layoutX="247.0" layoutY="104.0" mnemonicParsing="false" onAction="#generateRandomNumber" prefHeight="32.0" prefWidth="102.0" text="Random" />
</children></AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
</children>
<columnConstraints>
<ColumnConstraints />
</columnConstraints>
<rowConstraints>
<RowConstraints />
</rowConstraints>
</GridPane>
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane prefHeight="400" prefWidth="900" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.NimGameController">
<children>
<TableView fx:id="tableView" layoutX="681.0" layoutY="14.0" prefHeight="282.0" prefWidth="205.0">
<columns>
</columns>
</TableView>
<Button layoutX="787.0" layoutY="353.0" mnemonicParsing="false" onAction="#back" prefHeight="32.0" prefWidth="99.0" text="Back" />
<Button layoutX="787.0" layoutY="305.0" mnemonicParsing="false" onAction="#showNumsForDebug" prefHeight="32.0" prefWidth="99.0" text="Show" />
</children>
</AnchorPane>
initialize()
,因此在调用fxmloader.load()
期间调用populateTable()
,这必然发生在调用setList(…)
之前
因此,当调用populateTable()
时,textinextfieldtolist
仍然为null,并且textinextfieldtolist.isEmpty()
抛出一个NullPointerException
只需将调用移动到populateTable
到setList()
。这是有意义的,因为在设置列表之前,您无法填充表,如果您下次调用setList()
,您可能需要重新填充表
public void setList(ObservableList<Node> textInTextFieldToList) {
this.textInTextFieldToList = textInTextFieldToList;
populateTable();
}
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
configureTable();
}
public void集合列表(observeList textInTextFieldToList){
this.textInTextFieldToList=textInTextFieldToList;
populateTable();
}
@凌驾
公共void初始化(URL、ResourceBundle、ResourceBundle){
configureTable();
}
这是否回答了您的问题?请看一下如何创建
public void setList(ObservableList<Node> textInTextFieldToList) {
this.textInTextFieldToList = textInTextFieldToList;
populateTable();
}
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
configureTable();
}