1

When I attempt to go from the main screen, which is a TableView to another scene which contains textboxes I receive a NullPointer Exception. All of the fxml objects are accounted for, and when I remove the setCellFactory values it transitions but there are no items displayed.

I have attempted to following: 1. Mapped all of the fxml items to ensure it is not null. 2. Separated all of the product display functions to separate classes.

Main.java

        package shoppingcart;

        import javafx.application.Application;
        import javafx.collections.FXCollections;
        import javafx.collections.ObservableList;
        import javafx.fxml.FXMLLoader;
        import javafx.scene.Parent;
        import javafx.scene.Scene;
        import javafx.scene.control.cell.PropertyValueFactory;
        import javafx.stage.Stage;

        public class Main extends Application {

            //Initializing Main Window
            Stage mainWindow;

            public static void main(String[] args) {
                launch(args);
            }

            @Override
            public void start(Stage primaryStage) throws Exception {
                mainWindow = primaryStage;

                Parent root = FXMLLoader.load(getClass().getResource("shoppingcart.fxml"));
                mainWindow.setScene(new Scene(root));

                mainWindow.show();
            }
        }

Products.java

        package shoppingcart;

        import javafx.beans.property.SimpleDoubleProperty;
        import javafx.beans.property.SimpleIntegerProperty;
        import javafx.beans.property.SimpleStringProperty;

        public class Products {
            //Variables used to populated Shopping Cart Table
            private SimpleStringProperty itemName;
            private SimpleStringProperty itemPriority;
            private SimpleIntegerProperty itemQty;
            private SimpleDoubleProperty itemPrice;

            public Products(String itemName, double itemPrice, String itemPriority, int itemQty) {
                this.itemName = new SimpleStringProperty(itemName);
                this.itemPrice = new SimpleDoubleProperty(itemPrice);
                this.itemPriority = new SimpleStringProperty(itemPriority);
                this.itemQty = new SimpleIntegerProperty(itemQty);
            }

            public String getItemName() {
                return itemName.get();
            }

            public void setItemName(String itemName) {
                this.itemName = new SimpleStringProperty(itemName);
            }

            public String getItemPriority() {
                return itemPriority.get();
            }

            public void setItemPriority(String itemPriority) {
                this.itemPriority = new SimpleStringProperty(itemPriority);
            }

            public int getItemQty() {
                return itemQty.get();
            }

            public void setItemQty(int itemQty) {
                this.itemQty = new SimpleIntegerProperty(itemQty);
            }

            public double getItemPrice() {
                return itemPrice.get();
            }
            public void setItemPrice(double itemPrice) {
                this.itemPrice = new SimpleDoubleProperty(itemPrice);
            }

            public String toString() {
                return String.format("%s %s", itemName, itemPriority);
            }
        }

Controller.java

        package shoppingcart;

        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.Node;
        import javafx.scene.Parent;
        import javafx.scene.Scene;
        import javafx.scene.control.*;
        import javafx.scene.control.cell.PropertyValueFactory;
        import javafx.scene.layout.AnchorPane;
        import javafx.scene.text.Text;
        import javafx.stage.Stage;

        import java.io.IOException;
        import java.net.URL;
        import java.util.ResourceBundle;

        public class Controller implements Initializable {

            //Capturing textfields used on Form
            @FXML
            private TextField productName;

            @FXML
            private TextField productQty;

            @FXML
            private TextField productPrice;

            @FXML
            private TextField productPriority;

            @FXML
            private AnchorPane productPage;

            @FXML
            private Button productAdd;

            @FXML
            private Button productHome;

            @FXML
            private Text labelitemName;

            @FXML
            private Text labelitemPriority;

            @FXML
            private Text labelitemQty;

            @FXML
            private Text labelitemPrice;

            //Table used for Shopping Cart
            @FXML
            private TableView<Products> item_Table;
            @FXML
            private TableColumn<Products, String> item_Priority;
            @FXML
            private TableColumn<Products, String> item_Name;
            @FXML
            private TableColumn<Products, Integer> item_Qty;
            @FXML
            private TableColumn<Products, Double> item_Price;

            //The Initializer used to load data prior to loading view.
            @Override
            public void initialize(URL url, ResourceBundle resourceBundle) {

                item_Priority.setCellValueFactory(new PropertyValueFactory<Products, String>("ItemPriority"));
                item_Name.setCellValueFactory(new PropertyValueFactory<Products, String>("ItemName"));
                item_Qty.setCellValueFactory(new PropertyValueFactory<Products, Integer>("ItemQty"));
                item_Price.setCellValueFactory(new PropertyValueFactory<Products, Double>("ItemPrice"));
                item_Table.setItems(getProduct());

                System.out.println("Loading user data.");
            }

            // Method used to get the list of products
            public ObservableList<Products> getProduct() {
                ObservableList<Products> products = FXCollections.observableArrayList();
                products.add(new Products("Orange", 2.00, "1", 1));
                return products;
            }

            public void addItems(ActionEvent event) throws IOException {

                Parent addItem_page = FXMLLoader.load(getClass().getResource("addItem.fxml"));
                Scene addItem_scene = new Scene(addItem_page);
                Stage addItem_stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
                addItem_stage.setScene(addItem_scene);
                addItem_stage.show();

                System.out.println("Displaying information to console: Ensuring the addItem method worked as expected.");
            }

            public void handleitemAdd() {
                System.out.println("Added item to cart test");
            }

            public void handleitemReturnCart(ActionEvent event) throws IOException {

                Parent shoppingCart_page = FXMLLoader.load(getClass().getResource("shoppingcart.fxml"));
                Scene shoppingCart_scene = new Scene(shoppingCart_page);
                Stage shoppingCart_stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
                shoppingCart_stage.setScene(shoppingCart_scene);
                shoppingCart_stage.show();

                System.out.println("Displaying information to console: Ensuring that user returned to main page");

            }

            public void handleitemDelete (ActionEvent event) throws IOException {

                System.out.println("Displaying information to console: Deleting Selected Item");
            }

        }

addItem.fxml


        <?xml version="1.0" encoding="UTF-8"?>

        <?import java.lang.*?>
        <?import javafx.scene.control.*?>
        <?import javafx.scene.control.Button?>
        <?import javafx.scene.control.TextField?>
        <?import javafx.scene.control.TitledPane?>
        <?import javafx.scene.layout.*?>
        <?import javafx.scene.layout.AnchorPane?>
        <?import javafx.scene.text.*?>
        <?import javafx.scene.text.Text?>

        <AnchorPane xmlns:fx="http://javafx.com/fxml/1" id="" fx:id="productPage" prefHeight="400.0" prefWidth="600.0"
                    xmlns="http://javafx.com/javafx/2.2" fx:controller="shoppingcart.Controller">
          <children>
            <TextField id="" fx:id="productName" layoutX="235.0" layoutY="118.0" prefWidth="200.0"/>
            <TextField id="" fx:id="productPrice" layoutX="235.0" layoutY="222.0" prefWidth="200.0"/>
            <TextField id="" fx:id="productQty" layoutX="235.0" layoutY="175.0" prefWidth="200.0"/>
            <TextField id="" fx:id="productPriority" layoutX="235.0" layoutY="64.0" prefWidth="200.0"/>
            <Text id="" fx:id="labelitemName" layoutX="85.0" layoutY="144.0" strokeType="OUTSIDE" strokeWidth="0.0"
                  text="Item Name:"/>
            <Text id="" fx:id="labelitemQty" layoutX="111.0" layoutY="207.0" strokeType="OUTSIDE" strokeWidth="0.0"
                  text="Item Qty:"/>
            <Text id="" fx:id="labelitemPriority" layoutX="79.0" layoutY="90.0" strokeType="OUTSIDE" strokeWidth="0.0"
                  text="Item Priority:"/>
            <Text id="" fx:id="labelitemPrice" layoutX="97.0" layoutY="251.0" scaleX="1.0" scaleY="0.9999961759667156"
                  strokeType="OUTSIDE" strokeWidth="0.0" text="Item Price:"/>
            <Button id="itemsAdd" fx:id="productAdd" layoutX="235.0" layoutY="287.0" onAction="#handleitemAdd" text="ADD"/>
            <Button id="returnCartHome" fx:id="productHome" layoutX="344.0" layoutY="287.0" mnemonicParsing="false"
                    onAction="#handleitemReturnCart" text="Return to Cart"/>
          </children>
        </AnchorPane>

shoppingCart.fxml


        <?xml version="1.0" encoding="UTF-8"?>

        <?import java.lang.*?>
        <?import javafx.scene.control.*?>
        <?import javafx.scene.control.Button?>
        <?import javafx.scene.control.TableColumn?>
        <?import javafx.scene.control.TableView?>
        <?import javafx.scene.layout.*?>
        <?import javafx.scene.layout.AnchorPane?>
        <?import javafx.scene.text.*?>
        <?import javafx.scene.text.Font?>
        <?import javafx.scene.text.Text?>

        <AnchorPane xmlns:fx="http://javafx.com/fxml/1" prefHeight="400.0" prefWidth="600.0"
                    xmlns="http://javafx.com/javafx/2.2" fx:controller="shoppingcart.Controller">
            <Button fx:id="itemsAdd" layoutX="29.0" layoutY="352.0" onAction="#addItems" text="Add Items to Cart"/>
            <TableView fx:id="item_Table" layoutX="29.0" layoutY="64.0" prefHeight="272.0" prefWidth="542.0"
                       tableMenuButtonVisible="true">
                <columnResizePolicy>
                    <TableView fx:constant="CONSTRAINED_RESIZE_POLICY"/>
                </columnResizePolicy>
                <columns>
                    <TableColumn editable="false" prefWidth="75.0" text="Priority" fx:id="item_Priority"/>
                    <TableColumn editable="false" prefWidth="75.0" text="Item Name" fx:id="item_Name"/>
                    <TableColumn editable="false" prefWidth="75.0" text="Item Qty" fx:id="item_Qty"/>
                    <TableColumn editable="false" prefWidth="75.0" text="Price" fx:id="item_Price"/>
                </columns>
            </TableView>
            <Text layoutX="44.0" layoutY="43.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Shopping Cart Application"
                  wrappingWidth="513.0000000000001">
                <font>
                    <Font size="44.0"/>
                </font>
            </Text>
            <Button id="itemsDelete" layoutX="312.0" layoutY="352.0" mnemonicParsing="false" onAction="#handleitemDelete"
                    text="Delete Selected Item"/>
        </AnchorPane>

Caused by: java.lang.NullPointerException
    at assignment_3/shoppingcart.Controller.initialize(Controller.java:74)
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2573)
poisn
  • 437
  • 2
  • 17
Freytes
  • 43
  • 10
  • Possible duplicate of [What is a NullPointerException, and how do I fix it?](https://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it) – poisn Sep 30 '19 at 05:29
  • It's similar but my issue is related to Javafx and the tableView, not just a non-initialized variable. – Freytes Sep 30 '19 at 12:51
  • Which line is line 74 in the `Controller.java` file? In the code you pasted it's the the `getProduct()` method declaration, so clearly not in the `initialize()` method. – Olivier Grégoire Sep 30 '19 at 12:58
  • `item_Priority.setCellValueFactory(new PropertyValueFactory("ItemPriority"));` `item_Name.setCellValueFactory(new PropertyValueFactory("ItemName"));` `item_Qty.setCellValueFactory(new PropertyValueFactory("ItemQty"));` `item_Price.setCellValueFactory(new PropertyValueFactory("ItemPrice"));` `item_Table.setItems(getProduct());` Are the lines which error out. – Freytes Sep 30 '19 at 13:07
  • 1
    Can you please create an [mcve](https://stackoverflow.com/help/minimal-reproducible-example) and show us where the exception get thrown (with the code). Most of the code here is not necessary and it just takes us time to go through the code line by line to see where the error is thrown. – poisn Sep 30 '19 at 13:14

1 Answers1

0

You use the same controller for both addItem.fxml and shoppingcart.fxml

Check both your fx:controller tags, you'll see that they both point to the same controller.

For the shoppingcart.fxml, it works because the controller is made for that fxml file. But for the addItem.fxml file, another instance of Controller is created and in that fxml file, the elements item_Priority (and friends) are not defined, so they are not injected in the controller.

There are two solutions:

  1. create an AddItemController to specifically handle the addItem.fxml and move all that logic there, or...
  2. in the initialize method, check if itemTable is not null and do something in that case

    @Override public void initialize(URL url, ResourceBundle resourceBundle) {
      if (item_Table != null) {
        item_Priority.setCellValueFactory(new PropertyValueFactory<Products, String>("ItemPriority"));
        item_Name.setCellValueFactory(new PropertyValueFactory<Products, String>("ItemName"));
        item_Qty.setCellValueFactory(new PropertyValueFactory<Products, Integer>("ItemQty"));
        item_Price.setCellValueFactory(new PropertyValueFactory<Products, Double>("ItemPrice"));
        item_Table.setItems(getProduct());
      }
    }
    

For ease of use, I would definitely use the solution 1.

Olivier Grégoire
  • 33,839
  • 23
  • 96
  • 137
  • That works! I appreciate it. I will create another controller and move over the logic. – Freytes Sep 30 '19 at 13:33
  • 1
    @Freytes Glad I helped you! I would however strongly consider using `` **``** `` instead of adding those in your initializer. – Olivier Grégoire Sep 30 '19 at 13:40
  • I implemented that both suggestions (creating a new controller and setting the PropertyValueFactory) and it all works as expected. Thank you so much for your time. – Freytes Sep 30 '19 at 13:58
  • Beware - option 2 is not an option: while technically possible to load 2 fxml files with the same controller, they create 2 different instances thus leaving one set of injected fields null – kleopatra Sep 30 '19 at 15:20
  • @kleopatra that's what I wrote in the second paragraph – Olivier Grégoire Sep 30 '19 at 18:14