javafx在尝试用项目填充textview时引发空指针异常

whitzsjs  于 2021-07-12  发布在  Java
关注(0)|答案(1)|浏览(311)

我试图为学校创建一个简单的javafx项目,让用户玩nim游戏。在我看来,这个概念很简单,因为我以前已经使用过java和javafx。当我试图通过传入一个可观察列表来设置tableview中的项时,出现了错误。我确信列表中包含我应该能够添加的对象。我不知道怎么了。
以下是我的全部代码:
主控制器类:

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));
    }
}

nimgamecontroller类:

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");
        }
    }
}

formatstringvaluefortableview类:

package format;

import entities.Node;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

public class FormatStringValueForTableView {

    public ObservableList<Node> formatString(String numberString) {
        ObservableList<Node> list = FXCollections.observableArrayList();
        for(int i = 0; i < numberString.length(); i++) {
            if(Character.isDigit(numberString.charAt(i)))
                list.add(new Node(getIntValueFromChar(numberString.charAt(i))));
        }
        return list;
    }

    public Integer getIntValueFromChar(char c) {
        return Integer.parseInt(String.valueOf(c));
    }

}

节点类:

package entities;

public class Node {

    private Integer value;
    private Integer level;
    private Integer functionValue;

    public Node(Integer value) {
        this.value = value;
        this.level = 0;
        this.functionValue = 0;
    }

    public Integer getValue() {
        return value;
    }

    public void setValue(Integer value) {
        this.value = value;
    }

    public Integer getLevel() {
        return level;
    }

    public void setLevel(Integer level) {
        this.level = level;
    }

    public Integer getFunctionValue() {
        return functionValue;
    }

    public void setFunctionValue(Integer functionValue) {
        this.functionValue = functionValue;
    }

    @Override
    public String toString() {
        return "Node{" +
                "value=" + value +
                ", level=" + level +
                ", functionValue=" + functionValue +
                '}';
    }
}

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>

nim\u game.fxml文件:

<?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>

以下是堆栈跟踪:

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1787)
    at javafx.fxml/javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1670)
    at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
    at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
    at javafx.graphics/javafx.scene.Node.fireEvent(Node.java:8879)
    at javafx.controls/javafx.scene.control.Button.fire(Button.java:200)
    at javafx.controls/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:206)
    at javafx.controls/com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
    at javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
    at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
    at javafx.graphics/javafx.scene.Scene$MouseHandler.process(Scene.java:3851)
    at javafx.graphics/javafx.scene.Scene$MouseHandler.access$1200(Scene.java:3579)
    at javafx.graphics/javafx.scene.Scene.processMouseEvent(Scene.java:1849)
    at javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2588)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:397)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:434)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:390)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:433)
    at javafx.graphics/com.sun.glass.ui.View.handleMouseEvent(View.java:556)
    at javafx.graphics/com.sun.glass.ui.View.notifyMouse(View.java:942)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:76)
    at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at javafx.base/com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:273)
    at javafx.fxml/com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:83)
    at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1782)
    ... 51 more
Caused by: javafx.fxml.LoadException: 
/C:/Users/marci/IDEAPROJECTS/NimGameWithMINIMAX/target/classes/ui/nim_game.fxml

    at javafx.fxml/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2625)
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2603)
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2466)
    at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:2435)
    at controllers.MainController.continueToGame(MainController.java:25)
    ... 62 more
Caused by: java.lang.NullPointerException
    at controllers.NimGameController.populateTable(NimGameController.java:73)
    at controllers.NimGameController.initialize(NimGameController.java:34)
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2573)
    ... 65 more
0ve6wy6x

0ve6wy6x1#

initialize() ,因此 populateTable() ,在调用 FXMLLoader.load() 在你打电话之前 setList(...) .
因此当 populateTable() 被调用, textInTextFieldToList 仍然为空并且 textInTextFieldToList.isEmpty() 抛出 NullPointerException .
只需将呼叫移动到 populateTablesetList() . 这是有意义的,因为在设置列表之前不能填充表,如果要调用 setList() 另一次,你可能想重新填充表。

public void setList(ObservableList<Node> textInTextFieldToList) {
    this.textInTextFieldToList = textInTextFieldToList;
    populateTable();
}

@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
    configureTable();
}

相关问题