2016-12-01 83 views
2

您好,這是我作爲Java和GUI設計新手的第一個問題。 我遇到了一個奇怪的情況,我覺得我只是看着。 我有一些信息的TableView,它也可以添加按鈕。刪除按鈕在我添加FilterList構造函數之前工作,以便我可以通過ID篩選搜索結果。一旦我添加了該功能,刪除按鈕停止工作。我個人認爲deleteButtonClicked類不再適當地檢測表格,因爲通過添加Filter功能進行了更改。但儘管我努力保持這兩者,但其中一個或另一個通常停止工作。我目前正試圖讓它在沒有刪除按鈕類的情況下工作,也許只需將產品設置爲空即可。JavaFX GUI - 爲什麼刪除按鈕功能不適用於TableView?

的TableView中功能的代碼的頂部,而刪除按鈕和功能是向底部。

package application; 

import javafx.application.Application; 
import static javafx.application.Application.launch; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.collections.transformation.FilteredList; 
import javafx.event.ActionEvent; 
import javafx.event.EventHandler; 
import javafx.geometry.Insets; 
import javafx.geometry.Pos; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.Label; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableColumn.CellEditEvent; 
import javafx.scene.control.TableView; 
import javafx.scene.control.TextField; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.VBox; 
import javafx.scene.text.Font; 
import javafx.stage.Stage; 
import javafx.scene.control.cell.PropertyValueFactory; 
import javafx.scene.control.cell.TextFieldTableCell; 
import javafx.scene.layout.HBox; 
import javafx.scene.text.FontWeight; 
import javafx.scene.text.Text; 

public class MainApp extends Application { 



    TableView<Product> table = new TableView<>(); 


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

    @Override 
    public void start(Stage primaryStage) throws Exception { 
     BorderPane root = new BorderPane(); 

     BorderPane leftPane = new BorderPane(); 

     FilteredList<Product> filterList = new FilteredList<>(productData); 

     table.setEditable(true); 
     //table.setItems(productData); // DELETE BUTTON WORKS WHEN THIS ONE IS ONLY SET 
     table.setItems(filterList); // DELETE BUTTON DOESN'T WORK WHEN 
            // THIS IS SET BUT, IS NEEDED TO FILTER SEARCH FUNCTIONS 

     TableColumn<Product, String> idNumberCol = new TableColumn<>("ID Number"); 
     idNumberCol.setMinWidth(50); 
     idNumberCol.setCellValueFactory(new PropertyValueFactory<>("idNumber")); 

     idNumberCol.setCellFactory(TextFieldTableCell.<Product>forTableColumn()); 
     idNumberCol.setOnEditCommit(
     (CellEditEvent<Product, String> t) -> { 
     ((Product) t.getTableView().getItems().get(
      t.getTablePosition().getRow()) 
      ).setIdNumber(t.getNewValue()); 
}); 

     TableColumn<Product, String> desCol = new TableColumn<>("Description"); 
     desCol.setMinWidth(150); 
     desCol.setCellValueFactory(new PropertyValueFactory<>("description")); 

     desCol.setCellFactory(TextFieldTableCell.<Product>forTableColumn()); 
     desCol.setOnEditCommit(
     (CellEditEvent<Product, String> t) -> { 
     ((Product) t.getTableView().getItems().get(
      t.getTablePosition().getRow()) 
      ).setDescription(t.getNewValue()); 
}); 

     TableColumn<Product, String> expCol = new TableColumn<>("Expiration"); 
     expCol.setMinWidth(100); 
     expCol.setCellValueFactory(new PropertyValueFactory<>("expiration")); 

     expCol.setCellFactory(TextFieldTableCell.<Product>forTableColumn()); 
     expCol.setOnEditCommit(
     (CellEditEvent<Product, String> t) -> { 
     ((Product) t.getTableView().getItems().get(
      t.getTablePosition().getRow()) 
      ).setExpiration(t.getNewValue()); 
}); 


     table.getColumns().addAll(idNumberCol, desCol, expCol); 


     VBox leftVbox = new VBox(); 
     leftVbox.setPadding(new Insets(10, 20, 20, 20)); 
     leftVbox.setSpacing(10); 
     leftVbox.getChildren().addAll(table); 

     BorderPane topPane = new BorderPane(); 

     HBox topHbox = new HBox(); //Create HBox 
     topHbox.setPadding(new Insets(20, 20, 10, 20)); // Set padding and spacing for the hbox 
     topHbox.setSpacing(10); // The hbox will appropriately space out more 

     Text txtSearch = new Text("Search: "); 
     topHbox.getChildren().add(txtSearch); 
     txtSearch.setFont(Font.font("Tahoma", FontWeight.NORMAL, 16)); 

     TextField txt = new TextField(""); // Create new TextField 
     txt.setPrefWidth(250); 
     txt.setPromptText("Search A Product ID"); // Sets up hint text inside the TextField 
     topHbox.getChildren().add(txt); // Add the TextField to the second hbox 

     HBox rightHbox = new HBox(); //Create HBox 
     rightHbox.setPadding(new Insets(20, 20, 10, 20)); // Set padding and spacing for the hbox 
     rightHbox.setSpacing(10); // The hbox will appropriately space out more 

     Text txtDetails = new Text("Product Details"); 
     rightHbox.getChildren().add(txtDetails); 
     txtDetails.setFont(Font.font("Tahoma", FontWeight.NORMAL, 20)); 

     txt.textProperty().addListener((obsVal, oldValue, newValue) -> { 
     filterList.setPredicate(product -> product.getIdNumber().contains(newValue)); 
     }); 


     BorderPane rightPane = new BorderPane(); 

     VBox rightVbox = new VBox(); 
     rightVbox.setPadding(new Insets(20, 10, 10, 20)); 
     rightVbox.setSpacing(30); 
     rightVbox.setAlignment(Pos.TOP_LEFT); 

     Text txtId = new Text("ID: "); 
     rightVbox.getChildren().add(txtId); 
     txtId.setFont(Font.font("Tahoma", FontWeight.NORMAL, 16)); 

     Text txtDes = new Text("Description: "); 
     rightVbox.getChildren().add(txtDes); 
     txtDes.setFont(Font.font("Tahoma", FontWeight.NORMAL, 16)); 

     Text txtExp = new Text("Expiration: "); 
     rightVbox.getChildren().add(txtExp); 
     txtExp.setFont(Font.font("Tahoma", FontWeight.NORMAL, 16)); 

     Text txtStatus = new Text("Status: "); 
     rightVbox.getChildren().add(txtStatus); 
     txtStatus.setFont(Font.font("Tahoma", FontWeight.NORMAL, 16)); 

     Text txtEnter = new Text("Entered By: "); 
     rightVbox.getChildren().add(txtEnter); 
     txtEnter.setFont(Font.font("Tahoma", FontWeight.NORMAL, 16)); 

     //EMPTY PLACE HOLDER INFORMATION TO POPULATE THE DATA 
     Label lblId; 
     Label lblDes; 
     Label lblExp; 
     Label lblStatus; 
     Label lblEnter; 

     HBox bottomHbox2 = new HBox(); 
     bottomHbox2.setPadding(new Insets(20, 20, 20, 20)); 
     bottomHbox2.setSpacing(10); 
     bottomHbox2.setAlignment(Pos.BOTTOM_RIGHT); 


     Button btnNew = new Button("Add..."); 
     bottomHbox2.getChildren().add(btnNew); 
     btnNew.setOnAction(new EventHandler<ActionEvent>() { 
      @Override 
      public void handle(ActionEvent event) { 

      Stage secondStage = new Stage(); 

      BorderPane dialogPane = new BorderPane(); 

      VBox dialogVbox = new VBox(); 
      dialogVbox.setPadding(new Insets(20, 10, 20, 20)); 
      dialogVbox.setSpacing(20);  

      TextField addId = new TextField(); 
      addId.setPromptText("ID Number"); 
      addId.setMinWidth(50); 
      //addId.setMaxWidth(idNumberCol.getPrefWidth()); 

      TextField addDes = new TextField(); 
      addDes.setPromptText("Description"); 
      addDes.setMinWidth(100); 
      //addDes.setMaxWidth(desCol.getPrefWidth()); 

      TextField addExp = new TextField(); 
      addExp.setPromptText("Expiration Date"); 
      addExp.setMinWidth(50); 
      //addExp.setMaxWidth(expCol.getPrefWidth()); 

      dialogVbox.getChildren().addAll(addId, addDes, addExp); 

      VBox dialogVbox2 = new VBox(); 
      dialogVbox2.setPadding(new Insets(20, 20, 20, 10)); 
      dialogVbox2.setSpacing(20);  

      Text txtIdLabel = new Text("ID: "); 
      dialogVbox2.getChildren().add(txtIdLabel); 
      txtIdLabel.setFont(Font.font("Tahoma", FontWeight.NORMAL, 16)); 

      Text txtDesLabel = new Text("Description: "); 
      dialogVbox2.getChildren().add(txtDesLabel); 
      txtDesLabel.setFont(Font.font("Tahoma", FontWeight.NORMAL, 16)); 

      Text txtExpLabel = new Text("Expiration: "); 
      dialogVbox2.getChildren().add(txtExpLabel); 
      txtExpLabel.setFont(Font.font("Tahoma", FontWeight.NORMAL, 16)); 

      HBox addHbox = new HBox(); 
      addHbox.setPadding(new Insets(20, 10, 50, 20)); 
      addHbox.setSpacing(10); 
      addHbox.setAlignment(Pos.BOTTOM_RIGHT); 

      Button btnAdd = new Button("Add Product"); 
      addHbox.getChildren().add(btnAdd); 

      btnAdd.setOnAction((ActionEvent e) -> { 
      productData.add(new Product(
        addId.getText(), 
        addDes.getText(), 
        addExp.getText())); 
      addId.clear(); 
      addDes.clear(); 
      addExp.clear(); 
     }); 

       Button btnClose = new Button("Close"); 
     addHbox.getChildren().add(btnClose); 

     btnClose.setOnAction(new EventHandler<ActionEvent>(){ 

       @Override 
       public void handle(ActionEvent arg0) { 
        secondStage.close(); 
       } 

      }); 

      dialogPane.setCenter(dialogVbox); 
      dialogPane.setLeft(dialogVbox2); 
      dialogPane.setBottom(addHbox); 

      Scene scene2 = new Scene(dialogPane, 400, 200); 

      secondStage.setTitle("Add New Product"); 
      secondStage.setScene(scene2); 
      secondStage.show(); 

       //Set position of second window, related to primary window. 
       secondStage.setX(primaryStage.getX() + 250); 
       secondStage.setY(primaryStage.getY() + 100); 

       secondStage.show(); 
      } 
     }); 

     // DELETE BUTTON & EVENT HANDLER 
     Button btnDelete = new Button("Delete"); 
     bottomHbox2.getChildren().add(btnDelete); 

     btnDelete.setOnAction(new EventHandler<ActionEvent>(){ 

       @Override 
       public void handle(ActionEvent arg0) { 
        deleteButtonClicked(); 
       } 

      }); 


     Button btnSave = new Button("Save & Exit"); 
     bottomHbox2.getChildren().add(btnSave); 

     btnSave.setOnAction(new EventHandler<ActionEvent>(){ 

       @Override 
       public void handle(ActionEvent arg0) { 
        primaryStage.close(); 
       } 

      }); 

     rightVbox.getChildren().add(bottomHbox2); 

     topPane.setLeft(topHbox); 
     topPane.setCenter(rightHbox); 
     leftPane.setLeft(leftVbox); 
     rightPane.setLeft(rightVbox); 
     //rightPane.setCenter(bottomHbox2); 

     root.setTop(topPane); 
     root.setLeft(leftPane); 
     root.setCenter(rightPane); 

     Scene scene = new Scene(root, 650, 500); 
     primaryStage.setTitle("Perishables Application"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    // DELETE BUTTON FUNCTION 
    public void deleteButtonClicked() { 
     ObservableList<Product> productSelected, productData; 
     productData = table.getItems(); 
     productSelected = table.getSelectionModel().getSelectedItems(); 

     productSelected.forEach(productData::remove); 
    } 

    public ObservableList<Product> productData = FXCollections.observableArrayList(
    new Product("001", "Cereal", "1/1/2017"), 
    new Product("002", "Dog Food", "3/3/2017"), 
    new Product("003", "Juice", "1/1/2018") 
    ); 


} 

任何建議,非常感謝。謝謝閱讀。

回答

1

你有這樣的錯誤:

Exception in thread "JavaFX Application Thread" java.lang.UnsupportedOperationException at java.util.AbstractList.remove(AbstractList.java:161) at java.util.AbstractList$Itr.remove(AbstractList.java:374) at java.util.AbstractCollection.remove(AbstractCollection.java:293) at application.MainApp.deleteButtonClicked(MainApp.java:297) at application.MainApp$2.handle(MainApp.java:255) at application.MainApp$2.handle(MainApp.java:1)

嘗試用替換productSelected.forEach(productData::remove);

productSelected.forEach(this.productData::remove); 
          | 

提到,你想從ObservableList不是FilteredList,刪除數據刪除時他們從ObservableList它將被自動從th中刪除ËFilteredList<Product>


如果您想寫信給你用最少的代碼方法:

// DELETE BUTTON FUNCTION 
    public void deleteButtonClicked() { 
    table.getSelectionModel().getSelectedItems().forEach(this.productData::remove); 
    } 
+0

哇謝謝你,工作和一個非常簡單的解決方案了。 做了「這個」。工作,因爲它會直接引用當前對象? 您是否願意簡單解釋一下爲什麼需要在這種情況下?因爲就像我之前解釋的那樣,沒有它就可以正常工作,所以這就是讓我困惑的原因。再次感謝。 – BecauseTurtles

+0

@BecauseTurtles之前在你的代碼你在哪裏使用'.getItems()'所以你回來了'FilteredList ',並試圖從它。但是刪除項目的'FilteredList '本來就具有'ObservableList'的物品,所以你想從'ObservableList'中刪除這些項目。這樣做會自動從'FilteredList '中移除。我使用'this'來引用外部'ObservableList'。 – GOXR3PLUS