javajavafxfiltertableviewnstableviewcell

Filter a tableView leaves some data in a specific column


I have made my table view with column and everything works fine.

just one thing that I have remarked is that when I filter rows, some data stay in a column that I have defined its cellFactory.

Image showing the problem:
enter image description here

code of the column:

 @FXML
        private TableColumn<Log, Integer> colQuanJour;

colQuanJour.setCellValueFactory(new PropertyValueFactory<>("quantite"));

CellFactory to add color and character (+ or -)

colQuanJour.setCellFactory( 
               new Callback<TableColumn<Log,Integer>,TableCell<Log,Integer>>(){
           @Override
           public TableCell<Log, Integer> call(TableColumn<Log, Integer> param) {
              return new TableCell<Log, Integer>(){
                  @Override
                  protected void updateItem(Integer item, boolean empty) {
                      if( ! empty){
                         
                          int currIndex = indexProperty().getValue() < 0 ? 0 
                                  : indexProperty().getValue();
                          
                          int operIndex = param.getTableView().getItems().get(currIndex).getOperation().getId_operation();
                          setStyle("-fx-font-weight: bold");
                          String Char ;
                          if(operIndex == 2){
                              setStyle("-fx-font-size : 16px");
                              setStyle("-fx-text-fill : red");
                               Char = "-";
                          }else {
                              setStyle("-fx-font-size : 16px");
                              setStyle("-fx-text-fill : green");
                               Char = "+";
                          }
                          String val = String.valueOf(param.getTableView().getItems().get(currIndex).getQuantite());
                          setText(Char+val);
                      }
                  }
                  
              };
               
           }
        
        });

Log is a pojo that contains a property quantity (SimpleIntegerProperty).

and my table is

TableView<Log> tblart;

function to filter:

this function takes the value from the comboBox to choose which column to use to filter, by default it filter from all the table as shown below:

   void filterOneJour(String id,String newVal){
    ObservableList<Log> obsList = FXCollections.observableArrayList();

    for(Log jour : tblJour.getItems()){
                String num = String.valueOf(jour.getNum());
                String qte = String.valueOf(jour.        
                switch(id){
        
                    case "Numéro" : 
                        if(num.toUpperCase().contains(newVal))
                            obsList.add(jour);break;
                  
                    case "Quantité":
                        if(qte.toUpperCase().contains(newVal))
                            obsList.add(jour);break;
                  
                    default : 
                        if(num.toUpperCase().contains( qte.toUpperCase().contains(newVal) )
                            obsList.add(jour);
                }         
    }
    tblJour.setItems(obsList);
            
}

So I hope that Everything is clear, I think the problem come from cellFactory and more exactly the updateItem.


Solution

  • Yes as you mentioned the problem is from updateItem method. TableView (acutally VirtualFlow) is rendered by using same rows/cells to avoid performance issues. The row/cell updateItem will be called based on the provided item. In your case, you only added to update the cell if the item is present and ignored it when it is empty. So the cell will not get updated for empty rows.

    To fix your issue.. you need to add the else condition.

    colQuanJour.setCellFactory( 
                   new Callback<TableColumn<Log,Integer>,TableCell<Log,Integer>>(){
               @Override
               public TableCell<Log, Integer> call(TableColumn<Log, Integer> param) {
                  return new TableCell<Log, Integer>(){
                      @Override
                      protected void updateItem(Integer item, boolean empty) {
                          if( ! empty){
                              // Your code...
                              setText(Char+val);
                          }else{
                              setText(null); // This will clear the text for empty rows
                          }
                      }
                  };
               }
            });