1

我在我正在使用的主屏幕上有兩個表格。從文本字段中提取空數據。表已填充,但無法檢索對象。 Java/JavaFX

零件表和產品表。產品由零件組成。零件表(搜索,選擇等)的表功能都可以正常工作。當一個新產品被創建並添加到表中時,它似乎就在那裏。但是,當我試圖檢索數據進行修改時,通過用數據初始化產品字段,我得到了一個N​​PE。當使用與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> 
+1

代碼中的哪個位置可以獲得NPE? –

+0

這是在不同的代碼部分,我無法發佈。這是我第一次發表SO/SE的文章,它說我已經超過了我的人物數量。我還有兩個其他文件可以發佈。 我的修復程序是在我的.fxml文件中,我沒有fx:id條目,用於我試圖填充的字段。菜鳥犯的菜鳥錯誤。所以一旦我糾正了fx:id條目來匹配我的字段名稱,我沒事。 我非常想發佈我的其他代碼,這樣人們可能會失去我的錯誤,但不知道如何處理字符計數通知! –

回答

-1

我解決我自己的問題。這個問題最終出現在我的.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

如果你充實了這個(也許是一個好的塊),這甚至可能是一個答案。 –

相關問題