从文本字段中提取空数据。表已填充,但无法检索对象。 Java/JavaFX
问题描述:
我在我正在使用的主屏幕上有两个表格。从文本字段中提取空数据。表已填充,但无法检索对象。 Java/JavaFX
零件表和产品表。产品由零件组成。零件表(搜索,选择等)的表功能都可以正常工作。当一个新产品被创建并添加到表中时,它似乎就在那里。但是,当我试图检索数据进行修改时,通过用数据初始化产品字段,我得到了一个NPE。当使用与Part表相同的搜索功能时,搜索功能找不到该零件。
列出的是有问题的文件...
MainScreenController.java
/**
* Sample Skeleton for 'MainScreen.fxml' Controller Class
*/
package jbernsd_IMS.View;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.collections.transformation.SortedList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import jbernsd_IMS.MainApp;
import jbernsd_IMS.Model.Inventory;
import jbernsd_IMS.Model.Part;
import jbernsd_IMS.Model.Product;
public class MainScreenController {
// Table and column declarations for Part table.
// fx:id partTableMain
@FXML
private TableView<Part> partTableMain;
// fx:ids are respective...ie partIdColumnMain, partInvColumnMain, etc.
@FXML
private TableColumn<Part, Integer> partIdColumnMain, partInvColumnMain;
// fx:id partNameColumnMain;
@FXML
private TableColumn<Part, String> partNameColumnMain;
// fx:id partCostColumnMain
@FXML
private TableColumn<Part, Double> partCostColumnMain;
// Table and column declarations for Product table.
// fx:id productTableMain
@FXML
private TableView<Product> productTableMain;
// fx:ids are respective...ie productIdColumnMain, productInvColumnMain, etc.
@FXML
private TableColumn<Product, Integer> productIdColumnMain, productInvColumnMain;
// fx:id productNameColumnMain
@FXML
private TableColumn<Product, String> productNameColumnMain;
// fx:id productCostColumnMain
@FXML
private TableColumn<Product, Double> productCostColumnMain;
// fx:ids are respective...ie addPartButtonMain, modPartButtonMain, etc.
@FXML
private Button addPartButtonMain, modPartButtonMain, delPartButtonMain, searchPartButtonMain,
addProductButtonMain, modProductButtonMain, delProductButtonMain, searchProductButtonMain,
exitButton;
// fx:ids are respective...ie searchPartFieldMain, searchProductFieldMain, etc.
@FXML
private TextField searchPartFieldMain, searchProductFieldMain;
private boolean okClicked = false;
// Reference to the main application...
private MainApp mainApp;
/**
* The MainScreenController (MSC) no-argument Constructor
* The constructor is called before the initialize() method.
*/
public MainScreenController() {
}
/**
* Initializes the controller class. This method is automatically called
* after the fxml file has been loaded.
*/
@FXML
private void initialize() {
partIdColumnMain.setCellValueFactory(cellData -> cellData.getValue().partIdProperty().asObject());
partNameColumnMain.setCellValueFactory(cellData -> cellData.getValue().partNameProperty());
partInvColumnMain.setCellValueFactory(cellData -> cellData.getValue().partInvProperty().asObject());
partCostColumnMain.setCellValueFactory(cellData -> cellData.getValue().partCostProperty().asObject());
productIdColumnMain.setCellValueFactory(cellData -> cellData.getValue().productIdProperty().asObject());
productNameColumnMain.setCellValueFactory(cellData -> cellData.getValue().productNameProperty());
productInvColumnMain.setCellValueFactory(cellData -> cellData.getValue().productInvProperty().asObject());
productCostColumnMain.setCellValueFactory(cellData -> cellData.getValue().productCostProperty().asObject());
}
// setText(String.format("%0.2f", value.doubleValue()));
/**
* Is called by the main application to give reference to itself.
*
* @param mainApp
*/
public void setMainApp(MainApp mainApp) {
this.mainApp = mainApp;
// Add observable list data to the table
partTableMain.setItems(Inventory.getAllParts());
productTableMain.setItems(Inventory.getProducts());
}
// onAction="#handleNewPart"
@FXML
private void handleNewPart() {
okClicked = mainApp.showAddPartScreen();
}
// onAction="#handleNewProduct"
@FXML
private void handleNewProduct() {
okClicked = mainApp.showAddProductScreen();
}
// onAction="#handleModPart"
@FXML
private void handleModPart(ActionEvent e) {
Inventory.selectedPart = partTableMain.getSelectionModel().getSelectedItem();
Part selectedPart = Inventory.selectedPart;
if(selectedPart != null) {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle("Selection Confirmation");
alert.setHeaderText("Please confirm the part you selected...");
alert.setContentText("You have selected: \n\n"
+ "Part ID: \t\t" + selectedPart.partIdProperty().getValue() + "\n"
+ "Part Name: \t" + selectedPart.partNameProperty().getValueSafe() + "\n\n");
alert.showAndWait()
.filter(response -> response == ButtonType.OK)
.ifPresent(response -> mainApp.showModPartScreen());
okClicked = true;
} else { // //
// Nothing selected...
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setTitle("No selection");
alert.setHeaderText("No part selected");
alert.setContentText("Please select a part in the table.");
alert.showAndWait()
.filter(response -> response == ButtonType.OK)
.ifPresent(response -> alert.close());
okClicked = false;
}
}
// onAction="#handleModProduct"
@FXML
private void handleModProduct(ActionEvent e) {
// productTableMain.setOnMouseClicked((MouseEvent event) -> {
// if(event.getButton().equals(MouseButton.PRIMARY)) {}
// });
Inventory.selectedProduct = productTableMain.getSelectionModel().getSelectedItem();
Product selectedProduct = Inventory.selectedProduct;
if(selectedProduct != null) {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle("Selection Confirmation");
alert.setHeaderText("Please confirm the product you selected...");
alert.setContentText("You have selected: \n\n"
+ "Product ID: \t\t" + selectedProduct.productIdProperty().getValue() + "\n"
+ "Product Name: \t" + selectedProduct.productNameProperty().getValueSafe() + "\n\n");
alert.showAndWait()
.filter(response -> response == ButtonType.OK)
.ifPresent(response -> mainApp.showModProductScreen());
okClicked = true;
} else { // //
// Nothing selected...
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setTitle("No selection");
alert.setHeaderText("No products selected");
alert.setContentText("Please select a product in the table.");
alert.showAndWait()
.filter(response -> response == ButtonType.OK)
.ifPresent(response -> alert.close());
okClicked = false;
}
}
// fx:id foundMe
@FXML
private void foundMe() {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle("Easter Egg!! (Illegal after 9/11)");
alert.setHeaderText("Congratulations!!!");
alert.setContentText("Congratulations!! You found my Easter Egg!!! :) ");
alert.showAndWait();
}
@FXML
private void handleClose(ActionEvent e) {
Platform.exit();
}
/**
* Called when the user clicks on the delete button.
*/
@FXML
private void handleDelete(ActionEvent e) {
Part selectedPart = partTableMain.getSelectionModel().getSelectedItem();
if(selectedPart != null) {
// Confirm deletion
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle("Confirm Deletion");
alert.setHeaderText("Deleting...");
alert.setContentText("Are you sure you want to delete the part? \n\n"
+ "Part ID: \t\t" + selectedPart.partIdProperty().getValue() + "\n"
+ "Part Name: \t" + selectedPart.partNameProperty().getValueSafe());
alert.showAndWait()
.filter(response -> response == ButtonType.OK)
.ifPresent(response -> Inventory.getAllParts().remove(selectedPart));
// Update partTableMain
partTableMain.setItems(Inventory.getAllParts());
} else {
// Nothing selected...
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setTitle("No selection");
alert.setHeaderText("No part selected");
alert.setContentText("Please select a part in the table.");
alert.showAndWait();
}
}
@FXML
private void handleDeleteProd(ActionEvent e) {
Product selectedProduct = productTableMain.getSelectionModel().getSelectedItem();
if(selectedProduct != null) {
// Confirm deletion
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle("Confirm Deletion");
alert.setHeaderText("Deleting...");
alert.setContentText("Are you sure you want to delete the product? \n\n"
+ "Part ID: \t\t" + selectedProduct.productIdProperty().getValue() + "\n"
+ "Part Name: \t" + selectedProduct.productNameProperty().getValueSafe()); //
alert.showAndWait()
.filter(response -> response == ButtonType.OK)
.ifPresent(response -> Inventory.getProducts().remove(selectedProduct));
// Update partTableMain
productTableMain.setItems(Inventory.getProducts());
} else { // //
// Nothing selected...
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setTitle("No selection");
alert.setHeaderText("No product selected");
alert.setContentText("Please select a product in the table.");
alert.showAndWait();
}
}
@FXML
private void searchPartTable() {
String searchItem = searchPartFieldMain.getText();
if(isSearchInputValid(searchItem)) {
FilteredList<Part> searchPartResults = searchParts(searchItem);
SortedList<Part> sortedParts = new SortedList<>(searchPartResults);
sortedParts.comparatorProperty().bind(partTableMain.comparatorProperty());
partTableMain.setItems(sortedParts);
searchPartFieldMain.clear();
}
}
private FilteredList<Part> searchParts (String s) {
return Inventory.getAllParts().filtered(p -> p.getPartName().toLowerCase().contains(s.toLowerCase()));
}
@FXML
void searchProductTable() {
String searchItem = searchProductFieldMain.getText();
if(isSearchInputValid(searchItem)) {
FilteredList<Product> searchProductResults = searchProducts(searchItem);
SortedList<Product> sortedProducts = new SortedList<>(searchProductResults);
sortedProducts.comparatorProperty().bind(productTableMain.comparatorProperty());
productTableMain.setItems(sortedProducts);
}
}
public FilteredList<Product> searchProducts (String s) {
return Inventory.getProducts().filtered(p -> p.getProductName().contains(s.substring(0, 1).toUpperCase()
+ s.substring(1).toLowerCase()));
}
public boolean isSearchInputValid(String searchItem) {
ObservableList<Part> list = FXCollections.observableArrayList(Inventory.getAllParts());
String errorMessage = "";
String partName;
if(Inventory.getAllParts().isEmpty()) {
errorMessage += "Inv: \t\t There are no parts in inventory to search. \n\n";
}
if(!searchItem.equalsIgnoreCase("")) {
int count = 0;
for(Part p:Inventory.getAllParts()) {
String name = p.partNameProperty().getValueSafe();
if(!searchItem.equalsIgnoreCase(name) || searchItem.equals(null)) {
count++;
if(count == Inventory.getAllParts().size()) {
errorMessage += "Inv: \t\t The search item, " + "\"" + searchItem + "\"" + " does not match \n"
+ "\t\t any known items in the inventory. \n\n"
+ "\t\t The item cannot be found, or it does not exist. \n";
}
}
}
}
if(errorMessage.length() == 0) {
return true;
} else {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Error");
alert.setHeaderText("Data Error Exists");
alert.setContentText(errorMessage);
alert.showAndWait();
return false;
}
}
}
MainScreen.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.cell.PropertyValueFactory?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.shape.Rectangle?>
<?import javafx.scene.text.Font?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="jbernsd_IMS.View.MainScreenController">
<children>
<Rectangle fx:id="borderPartsMAIN" arcHeight="10.0" arcWidth="10.0" fill="TRANSPARENT" height="280.0" layoutX="25.0" layoutY="56.0" stroke="#979797" strokeLineCap="BUTT" strokeLineJoin="ROUND" strokeType="OUTSIDE" strokeWidth="2.0" width="366.0" />
<Label fx:id="labelInvMgmtSysMAIN" layoutX="18.0" layoutY="15.0" text=" Inventory Management System">
<font>
<Font name="Calibri Italic" size="24.0" />
</font>
</Label>
<!-- Parts section begins here -->
<TableView fx:id="partTableMain" layoutX="35.0" layoutY="95.0" prefHeight="188.0" prefWidth="344.0">
<columns>
<TableColumn fx:id="partIdColumnMain" prefWidth="54.0" text="Part ID">
<cellValueFactory>
<PropertyValueFactory property="partID" />
</cellValueFactory>
</TableColumn>
<TableColumn fx:id="partNameColumnMain" prefWidth="71.0" text="Part Name">
<cellValueFactory>
<PropertyValueFactory property="partName" />
</cellValueFactory>
</TableColumn>
<TableColumn fx:id="partInvColumnMain" minWidth="0.0" prefWidth="97.0" text="Inventory Level">
<cellValueFactory>
<PropertyValueFactory property="partInv" />
</cellValueFactory>
</TableColumn>
<TableColumn fx:id="partCostColumnMain" prefWidth="121.0" text="Price/Cost per Unit">
<cellValueFactory>
<PropertyValueFactory property="partCost" />
</cellValueFactory>
</TableColumn>
</columns>
</TableView>
<!-- Parts sections ends here -->
<Label fx:id="labelPartsPrtsMAIN" layoutX="36.0" layoutY="58.0" text="Parts">
<font>
<Font name="Calibri Italic" size="24.0" />
</font>
</Label>
<Button fx:id="searchPartButtonMain" layoutX="179.0" layoutY="63.0" mnemonicParsing="false" onAction="#searchPartTable" text="Search">
<font>
<Font name="Calibri Italic" size="12.0" />
</font></Button>
<TextField fx:id="searchPartFieldMain" layoutX="241.0" layoutY="63.0" prefHeight="25.0" prefWidth="136.0" />
<HBox layoutX="169.0" layoutY="294.0" spacing="15.0">
<children>
<Button fx:id="addPartButtonMain" mnemonicParsing="false" onAction="#handleNewPart" prefHeight="30.0" prefWidth="60.0" text="Add">
<font>
<Font name="Calibri Italic" size="12.0" />
</font></Button>
<Button fx:id="modPartButtonMain" mnemonicParsing="false" onAction="#handleModPart" prefHeight="30.0" prefWidth="60.0" text="Modify">
<font>
<Font name="Calibri Italic" size="12.0" />
</font></Button>
<Button fx:id="delPartButtonMain" mnemonicParsing="false" onAction="#handleDelete" prefHeight="30.0" prefWidth="60.0" text="Delete">
<font>
<Font name="Calibri Italic" size="12.0" />
</font></Button>
</children>
</HBox>
<!-- Parts section ends here -->
<!-- Products section begins here -->
<Rectangle fx:id="borderProdsMAIN" arcHeight="10.0" arcWidth="10.0" fill="TRANSPARENT" height="280.0" layoutX="410.0" layoutY="56.0" stroke="#979797" strokeLineCap="BUTT" strokeLineJoin="ROUND" strokeType="OUTSIDE" strokeWidth="2.0" width="370.0" />
<TableView fx:id="productTableMain" layoutX="420.0" layoutY="95.0" prefHeight="188.0" prefWidth="344.0">
<columns>
<TableColumn fx:id="productIdColumnMain" prefWidth="54.0" text="Prod ID" />
<TableColumn fx:id="productNameColumnMain" prefWidth="71.0" text="Prod Name" />
<TableColumn fx:id="productInvColumnMain" minWidth="0.0" prefWidth="97.0" text="Inventory Level" />
<TableColumn fx:id="productCostColumnMain" prefWidth="121.0" text="Price/Cost per Unit" />
</columns>
</TableView>
<Label fx:id="labelProdsMAIN" layoutX="421.0" layoutY="58.0" text="Products">
<font>
<Font name="Calibri Italic" size="24.0" />
</font>
</Label>
<Button fx:id="searchProductButtonMain" layoutX="564.0" layoutY="63.0" mnemonicParsing="false" onAction="#searchProductTable" text="Search">
<font>
<Font name="Calibri Italic" size="12.0" />
</font></Button>
<TextField fx:id="searchProductFieldMain" layoutX="626.0" layoutY="63.0" prefHeight="25.0" prefWidth="136.0" />
<HBox layoutX="554.0" layoutY="294.0" spacing="15.0">
<children>
<Button fx:id="addProductButtonMain" mnemonicParsing="false" onAction="#handleNewProduct" prefHeight="30.0" prefWidth="60.0" text="Add">
<font>
<Font name="Calibri Italic" size="12.0" />
</font></Button>
<Button fx:id="modProductButtonMain" mnemonicParsing="false" onAction="#handleModProduct" prefHeight="30.0" prefWidth="60.0" text="Modify">
<font>
<Font name="Calibri Italic" size="12.0" />
</font></Button>
<Button fx:id="delProductButtonMain" mnemonicParsing="false" onAction="#handleDeleteProd" prefHeight="30.0" prefWidth="60.0" text="Delete">
<font>
<Font name="Calibri Italic" size="12.0" />
</font></Button>
</children>
</HBox>
<Button fx:id="foundMe" layoutX="309.0" layoutY="109.0" mnemonicParsing="false" onAction="#foundMe" prefHeight="2.0" prefWidth="2.0" textFill="TRANSPARENT" AnchorPane.bottomAnchor="288.0" AnchorPane.leftAnchor="309.0" AnchorPane.rightAnchor="489.0" AnchorPane.topAnchor="109.0">
<font>
<Font size="2.0" />
</font>
</Button>
<Button fx:id="exitButton" layoutX="370.0" layoutY="356.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#handleClose" prefHeight="30.0" prefWidth="60.0" text="Exit">
<font>
<Font name="Calibri Italic" size="12.0" />
</font></Button>
<!-- Products section ends here -->
</children>
</AnchorPane>
答
我解决我自己的问题。这个问题最终出现在我的.fxml文件“ModifyProduct”中。没有fx:id对应于我试图填充的命名文本字段。所以即使我已经实例化了这些字段,并且由于缺乏可识别名称,我的大多数逻辑工作正常,但.fxml根本无法将数据与字段关联起来。一旦我解决了FX:ID名称在我.fxml文件时,数据流向正确...
ModifyProductController.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package jbernsd_IMS.View;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.collections.transformation.SortedList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import jbernsd_IMS.MainApp;
import jbernsd_IMS.Model.*;
/**
*
* @author JJ_2
*/
public class ModifyProductController {
private IntegerProperty partIdMP;
private IntegerProperty partNumberMP;
private StringProperty partNameMP;
private IntegerProperty partInvMP;
private IntegerProperty partCostMP;
public ModifyProductController() {
}
private MainApp mainApp;
private Label productIdLbl, productNameLbl, productInvLbl, productCostLbl, maxLbl, minLbl;
@FXML
private TextField productIdField, productNameField, productInvField, productCostField, minField, maxField, searchFieldModProds;
private final ObservableList<Part> importedParts = FXCollections.observableArrayList(Inventory.getAllParts());
private final ObservableList<Part> productParts = FXCollections.observableArrayList();
// Parts to add
// fx:id partTableAdd
@FXML
private TableView<Part> partTableAdd; // Stores the found parts to add to the product.
@FXML
private TableColumn<Part, Integer> partIdColumnAdd, partInvColumnAdd; // Holds the part ID and part Inv.
@FXML
private TableColumn<Part, String> partNameColumnAdd; // Holds the part Name.
@FXML
private TableColumn<Part, Double> partCostColumnAdd; // Holds the manufacturing cost of specified part.
// Parts to remove
// fx:id partTableDel
@FXML
private TableView<Part> partTableDel; // Stores the found parts to delete from the product.
@FXML
private TableColumn<Part, Integer> partIdColumnDel, partInvColumnDel; // Holds the part ID and part Inv.
@FXML
private TableColumn<Part, String> partNameColumnDel; // Holds the part Name.
@FXML
private TableColumn<Part, Double> partCostColumnDel; // Holds the manufacturing cost of specified part.
@FXML
private Stage dialogueStage;
@FXML
private boolean saveClicked = false;
@FXML
private boolean addClicked = false;
public ObservableList<Part> getProdParts() {
return productParts;
}
private Product draftProduct;
public Inventory inv;
public MainScreenController msc;
/**
* Initializes the controller class. This method is automatically called
* after the fxml file has been loaded.
*/
@FXML
private void initialize() {
// Set text fields.
setTextFields();
// part table (top)
partIdColumnAdd.setCellValueFactory(cellData -> cellData.getValue().partIdProperty().asObject());
partNameColumnAdd.setCellValueFactory(cellData -> cellData.getValue().partNameProperty());
partInvColumnAdd.setCellValueFactory(cellData -> cellData.getValue().partInvProperty().asObject());
partCostColumnAdd.setCellValueFactory(cellData -> cellData.getValue().partCostProperty().asObject());
partTableAdd.setItems(importedParts);
// part table (bottom)
partIdColumnDel.setCellValueFactory(cellData -> cellData.getValue().partIdProperty().asObject());
partNameColumnDel.setCellValueFactory(cellData -> cellData.getValue().partNameProperty());
partInvColumnDel.setCellValueFactory(cellData -> cellData.getValue().partInvProperty().asObject());
partCostColumnDel.setCellValueFactory(cellData -> cellData.getValue().partCostProperty().asObject());
}
/**
* Returns true if the user clicked OK, false otherwise.
*
* @return
*/
public boolean isSaveClicked() {
return saveClicked;
}
public boolean isAddClicked() {
return addClicked;
}
/**
* Called when the user clicks Add.
*/
@FXML
private void handleAdd() {
Part selectedPart = partTableAdd.getSelectionModel().getSelectedItem();
if (selectedPart != null) {
productParts.add(selectedPart);
partTableDel.getItems().add(selectedPart);
}
else {//part not selected
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setTitle("No Selection");
alert.setHeaderText("No part is selected");
alert.setContentText("Please select a part from the top table.");
alert.showAndWait();
}
}
/**
* Sets the stage of this dialogue
*
* @param dialogueStage
*/
@FXML
public void setDialogueStage(Stage dialogueStage) {
this.dialogueStage = dialogueStage;
}
// References MainApp
public void setMainApp(MainApp mainApp) {
this.mainApp = mainApp;
}
public void setTextFields() {
try {
productIdField.setText(Integer.toString(Inventory.selectedProduct.getProductId()));
productNameField.setText(Inventory.selectedProduct.getProductName());
productInvField.setText(Integer.toString(Inventory.selectedProduct.getProductInv()));
productCostField.setText(Double.toString(Inventory.selectedProduct.getProductCost()));
maxField.setText(Integer.toString(Inventory.selectedProduct.getMax()));
minField.setText(Integer.toString(Inventory.selectedProduct.getMin()));
} catch (NullPointerException e) {
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setTitle("Data Not Found");
alert.setHeaderText("Cannot find the requested data...");
alert.setContentText("The requested data is not being passed \n"+
"correctly. Check your code for data \n"+
"flow errors. \n\n" +
productIdField.getText()+ "\n" +
productNameField.getText()+ "\n" +
productInvField.getText()+ "\n" +
productCostField.getText()+ "\n" +
maxField.getText()+ "\n" +
minField.getText());
alert.showAndWait();
}
}
@FXML
public void handleSave() {
if(isInputValid()) {
draftProduct.setProductId(Integer.parseInt(productIdField.getText()));
draftProduct.setProductName(productNameField.getText());
draftProduct.setProductInv(Integer.parseInt(productInvField.getText()));
draftProduct.setProductCost(Double.parseDouble(productCostField.getText()));
draftProduct.setMax(Integer.parseInt(maxField.getText()));
draftProduct.setMin(Integer.parseInt(minField.getText()));
mainApp.getProductData().add(draftProduct);
}
dialogueStage.close();
}
/**
* Called when the user clicks cancel.
*/
@FXML
private void handleCancel() {
dialogueStage.close();
}
//------------------Working code, **** DO NOT DELETE **** -----------------------------------------------
private boolean isInputValid() {
String errorMessage = "";
// NO check needed for partID as it's auto-generated.
if(productNameField.getText().isEmpty() || productNameField.getText().matches("\\d+")) {
errorMessage += "Name: \t\t\t No valid product name!\n"
+ "\t\t\t\t Only letters are allowed. \n\n";
}
if(productInvField.getText().isEmpty() || !productInvField.getText().matches("\\d+")) {
errorMessage += "Inv: \t\t\t\t No valid inventory level!\n"
+ "\t\t\t\t Only numbers are allowed. \n\n";
} else if(productInvField.getText().compareToIgnoreCase(maxField.getText()) > 0) {
errorMessage += "Inv: \t\t\t\t Inv cannot exceed Max. \n\n";
} else if(productInvField.getText().compareToIgnoreCase(minField.getText()) < 0) {
errorMessage += "Inv: \t\t\t\t Inv cannot deceed Min. \n\n";
}
if(productCostField.getText().isEmpty() || !productCostField.getText().matches("\\d+\\.\\d+\\d+")) {
errorMessage += "Price/Cost: \t\t No valid cost figures!\n"
+ "\t\t\t\t Only numbers are allowed. \n\n";
}
if(maxField.getText().isEmpty() || !maxField.getText().matches("\\d+")) {
errorMessage += "Max: \t\t\t No valid maximum!\n"
+ "\t\t\t\t Only numbers are allowed. \n\n";
} else if(maxField.getText().compareToIgnoreCase(minField.getText()) < 0) {
errorMessage += "Max: \t\t\t Max may not deceed Min. \n\n";
}
if(minField.getText().isEmpty() || !minField.getText().matches("\\d+")) {
errorMessage += "Min: \t\t\t No valid minimum!\n"
+ "\t\t\t\t Only numbers are allowed. \n\n";
} else if(minField.getText().compareToIgnoreCase(maxField.getText()) > 0) {
errorMessage += "Min: \t\t\t Min may not exceed Max. \n\n";
}
if(partTableAdd.getItems().isEmpty()) {
errorMessage += "Imported Parts: \t There are currently no parts imported. \n"
+ "\t\t\t\t There must be parts imported to select\n"
+ "\t\t\t\t for inclusion in a new product!\n\n";
}
if(partTableDel.getItems().isEmpty()) {
errorMessage += "Product Parts: \t\t There are currently no parts to include. \n"
+ "\t\t\t\t There must be parts selected to\n"
+ "\t\t\t\t for inclusion to create a new product!\n\n";
}
if(errorMessage.length() == 0) {
return true;
} else {
// Show the error message
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.initOwner(dialogueStage);
alert.setTitle("Empty or Invalid Fields");
alert.setHeaderText("Please correct the empty or invalid fields");
alert.setContentText(errorMessage);
alert.show();
return false;
}
}
//------------------Working code, **** DO NOT DELETE **** -----------------------------------------------
@FXML
public void searchImportedParts() {
String searchItem = searchFieldModProds.getText();
FilteredList<Part> searchPartResults = searchPartsList(searchItem);
SortedList<Part> sortedParts = new SortedList<>(searchPartResults);
sortedParts.comparatorProperty().bind(partTableAdd.comparatorProperty());
partTableAdd.setItems(sortedParts);
}
public FilteredList<Part> searchPartsList (String s) {
return Inventory.getAllParts().filtered(p -> p.getPartName().toLowerCase().contains(s.toLowerCase()));
}
/**
* Called when the user clicks on the delete button.
*/
@FXML//------------------Working code, **** DO NOT DELETE **** -----------------------------------------------
private void handleDelete(ActionEvent e) {
Part selectedPart;
selectedPart = partTableDel.getSelectionModel().getSelectedItem();
if(selectedPart != null) {
// Confirm deletion
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle("Confirm Deletion");
alert.setHeaderText("Deleting...");
alert.setContentText("Are you sure you want to delete the part: " + "\'" + selectedPart.getPartName() + "\'" + "?"); //
alert.showAndWait()
.filter(response -> response == ButtonType.OK)
.ifPresent(response -> Inventory.getDelParts().remove(selectedPart));
// Update productTableMain
partTableDel.setItems(Inventory.getDelParts());
}else { // //
// Nothing selected...
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setTitle("No selection");
alert.setHeaderText("No product selected");
alert.setContentText("Please select a product in the table.");
alert.showAndWait();
}
} //------------------Working code, **** DO NOT DELETE **** -------------------------------------------------
}
ModifyProduct.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.shape.Rectangle?>
<?import javafx.scene.text.Font?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="500.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="jbernsd_IMS.View.ModifyProductController">
<children>
<Rectangle arcHeight="20.0" arcWidth="20.0" fill="TRANSPARENT" height="480.0" layoutX="10.0" layoutY="10.0" stroke="#979797" strokeType="OUTSIDE" strokeWidth="2.0" width="780.0" />
<TableView fx:id="partTableAdd" layoutX="386.0" layoutY="103.0" prefHeight="108.0" prefWidth="349.0">
<columns>
<TableColumn prefWidth="75.0" text="Part ID:" />
<TableColumn prefWidth="75.0" text="Part Name" />
<TableColumn prefWidth="102.0" text="Inventory Level" />
<TableColumn prefWidth="96.0" text="Price per Unit" />
</columns>
</TableView>
<TableView fx:id="partTableDel" layoutX="386.0" layoutY="290.0" prefHeight="108.0" prefWidth="349.0">
<columns>
<TableColumn prefWidth="75.0" text="Part ID:" />
<TableColumn prefWidth="75.0" text="Part Name" />
<TableColumn prefWidth="102.0" text="Inventory Level" />
<TableColumn prefWidth="96.0" text="Price per Unit" />
</columns>
</TableView>
<Button fx:id="addBtn" layoutX="665.0" layoutY="221.0" mnemonicParsing="false" onAction="#handleAdd" prefHeight="30.0" prefWidth="70.0" text="Add">
<font>
<Font name="Calibri Italic" size="12.0" />
</font>
</Button>
<Button fx:id="delBtn" layoutX="665.0" layoutY="408.0" mnemonicParsing="false" onAction="#handleDelete" prefHeight="30.0" prefWidth="70.0" text="Delete">
<font>
<Font name="Calibri Italic" size="12.0" />
</font></Button>
<Button fx:id="cancelBtn" layoutX="466.0" layoutY="446.0" mnemonicParsing="false" onAction="#handleCancel" prefHeight="30.0" prefWidth="70.0" text="Cancel">
<font>
<Font name="Calibri Italic" size="12.0" />
</font>
</Button>
<Button fx:id="saveBtn" layoutX="376.0" layoutY="446.0" mnemonicParsing="false" onAction="#handleSave" prefHeight="30.0" prefWidth="70.0" text="Save">
<font>
<Font name="Calibri Italic" size="12.0" />
</font>
</Button>
<TextField fx:id="searchFieldModProds" layoutX="536.0" layoutY="63.0" prefHeight="25.0" prefWidth="199.0">
<font>
<Font name="Calibri Italic" size="12.0" />
</font>
</TextField>
<Button fx:id="searchBtn" layoutX="456.0" layoutY="61.0" mnemonicParsing="false" onAction="#searchImportedParts" prefHeight="30.0" prefWidth="70.0" text="Search">
<font>
<Font name="Calibri Italic" size="12.0" />
</font>
</Button>
<TextField fx:id="idField" layoutX="98.0" layoutY="132.0" prefHeight="44.0" prefWidth="149.0" promptText="Auto Gen - Disabled">
<font>
<Font name="Calibri Italic" size="12.0" />
</font>
</TextField>
<Label fx:id="labelIdModProd" layoutX="29.0" layoutY="144.0" text="ID">
<font>
<Font name="Calibri Italic" size="14.0" />
</font>
</Label>
<TextField fx:id="nameField" layoutX="98.0" layoutY="182.0" prefHeight="44.0" prefWidth="149.0" promptText="Product Name">
<font>
<Font name="Calibri Italic" size="12.0" />
</font>
</TextField>
<Label fx:id="labelNameModProds" layoutX="29.0" layoutY="194.0" text="Name">
<font>
<Font name="Calibri Italic" size="14.0" />
</font>
</Label>
<TextField fx:id="invField" layoutX="98.0" layoutY="232.0" prefHeight="44.0" prefWidth="70.0" promptText="Inv">
<font>
<Font name="Calibri Italic" size="12.0" />
</font>
</TextField>
<Label fx:id="labelInvModProds" layoutX="29.0" layoutY="244.0" text="Inv">
<font>
<Font name="Calibri Italic" size="14.0" />
</font>
</Label>
<TextField fx:id="priceField" layoutX="98.0" layoutY="282.0" prefHeight="44.0" prefWidth="70.0" promptText="Price">
<font>
<Font name="Calibri Italic" size="12.0" />
</font>
</TextField>
<Label fx:id="labelPriceModProds" layoutX="29.0" layoutY="294.0" text="Price">
<font>
<Font name="Calibri Italic" size="14.0" />
</font>
</Label>
<TextField fx:id="maxField" layoutX="98.0" layoutY="332.0" prefHeight="44.0" prefWidth="70.0" promptText="Max">
<font>
<Font name="Calibri Italic" size="12.0" />
</font>
</TextField>
<Label fx:id="labelMaxModProds" layoutX="29.0" layoutY="344.0" text="Max">
<font>
<Font name="Calibri Italic" size="14.0" />
</font>
</Label>
<TextField fx:id="minField" layoutX="228.0" layoutY="332.0" prefHeight="44.0" prefWidth="70.0" promptText="Min">
<font>
<Font name="Calibri Italic" size="12.0" />
</font>
</TextField>
<Label fx:id="labelMinModProds" layoutX="185.0" layoutY="344.0" text="Min">
<font>
<Font name="Calibri Italic" size="14.0" />
</font>
</Label>
<Label fx:id="labelModifyPart" layoutX="34.0" layoutY="53.0" text="Modify Products">
<font>
<Font name="Calibri Bold Italic" size="24.0" />
</font>
</Label>
</children>
</AnchorPane>
刚必须记住匹配名称和其他标识符,并确保所有内容都指向应有的所有内容。谢谢大家的帮助!
+0
如果你充实了这个(也许是一个好的块),这甚至可能是一个答案。 –
代码中的哪个位置可以获得NPE? –
这是在不同的代码部分,我无法发布。这是我第一次发表SO/SE的文章,它说我已经超过了我的人物数量。我还有两个其他文件可以发布。 我的修复程序是在我的.fxml文件中,我没有fx:id条目,用于我试图填充的字段。菜鸟犯的菜鸟错误。所以一旦我纠正了fx:id条目来匹配我的字段名称,我没事。 我非常想发布我的其他代码,这样人们可能会失去我的错误,但不知道如何处理字符计数通知! –