从文本字段中提取空数据。表已填充,但无法检索对象。 Java/JavaFX
Posted
技术标签:
【中文标题】从文本字段中提取空数据。表已填充,但无法检索对象。 Java/JavaFX【英文标题】:Pulling null data from text fields. Table is populated, but can't retrieve objects. Java / JavaFX 【发布时间】:2018-02-06 04:19:21 【问题描述】:我正在使用的主屏幕上有两个表格。
零件表和产品表。产品由零件组成。零件表的表功能(搜索、选择等)都可以正常工作。当一个新产品被创建并添加到表中时,它似乎就在那里。但是,当我尝试检索数据以进行修改时,通过使用数据初始化 Product 字段,我得到一个 NPE。使用与零件表相同的搜索功能时,搜索功能不会找到零件。
列出的是有问题的文件...
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" layoutX="25.0" layoutY="56.0" stroke="#979797" strokeLineCap="BUTT" strokeLineJoin="ROUND" strokeType="OUTSIDE" strokeWidth="2.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" layoutX="410.0" layoutY="56.0" stroke="#979797" strokeLineCap="BUTT" strokeLineJoin="ROUND" strokeType="OUTSIDE" strokeWidth="2.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>
【问题讨论】:
你在代码的哪里得到 NPE? 这是在不同的代码部分,我无法发布。这是我第一次在 SO/SE 上发帖,上面说我的字符数超过了。我还有另外两个文件要发布。我的解决方法是在我的 .fxml 文件中,我尝试填充的字段没有 fx:id 条目。菜鸟犯的菜鸟错误。因此,一旦我更正了 fx:id 条目以匹配我的字段名称,我就没事了。我非常想发布我的其他代码,以便人们可以从我的错误中得到一些使用,但由于字符数通知而不确定如何使用! 【参考方案1】:我自己解决了问题。问题最终出在我的 .fxml 文件“ModifyProduct”中。没有与我试图填充的命名文本字段对应的 fx:id 等效项。因此,即使我已经实例化了这些字段,并且我的大部分逻辑都可以正常工作,但由于缺少可识别的名称,.fxml 根本无法将数据与字段相关联。一旦我解析了 .fxml 文件中的 fx:id 名称,数据就会正确流动......
修改ProductController.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 **** -------------------------------------------------
修改Product.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" layoutX="10.0" layoutY="10.0" stroke="#979797" strokeType="OUTSIDE" strokeWidth="2.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>
只需要记住匹配名称和其他标识符,并确保所有内容都指向它应该指向的其他所有内容。谢谢大家的帮助!!
【讨论】:
如果你充实了这个(也许是一个很好的部分),这甚至可能是一个答案。以上是关于从文本字段中提取空数据。表已填充,但无法检索对象。 Java/JavaFX的主要内容,如果未能解决你的问题,请参考以下文章
无法使用光标从数据库中成功检索Spinner选定的项目文本以填充我的应用程序中的联系人列表项目
如何从 Swift 中嵌入 UITableView 的文本字段中检索数据?