2017-02-17 111 views
0

我已經創建了自己的選擇列,並且在列標題中有一個複選框,當我單擊時更改了爲cellValueFactory設置的單元格的值,該單元格會觸發TableCell中的方法updateItem引發了我需要處理的自定義事件。TableView單元格updateItem不會調用視口外的單元格

public abstract class GeneratedPersistableBeanFX extends GeneratedPersistableBean { 

private static CheckBox select_all; 

public GeneratedPersistableBeanFX(int beanState) { 
    super(beanState); 
    // TODO Auto-generated constructor stub 
} 
private BooleanProperty SelectedInGridProperty = new SimpleBooleanProperty(false); 

public BooleanProperty selectedInGridProperty() { 
    return SelectedInGridProperty; 
} 

public Boolean getSelectedInGrid() { 
    return SelectedInGridProperty.getValue(); 
} 

public void setSelectedInGrid(Boolean val) { 
    SelectedInGridProperty.setValue(val); 
} 

public static CustomTableColumn<GeneratedPersistableBeanFX, Boolean> getTableColumnSelectedInGrid(String columnName) { 
    getSelectAllCheckBox(); 

    String columnHeader = ((columnName == null) ? "Selected" : columnName); 
    CustomTableColumn<GeneratedPersistableBeanFX, Boolean> theCol = new CustomTableColumn<>(columnHeader); 
    theCol.setId(columnHeader); 
    theCol.setMinWidth(32); 
    theCol.setColumnName(columnHeader); 
    theCol.setGraphic(getSelectAllCheckBox()); 
    theCol.setStyle("-fx-alignment: CENTER;"); 
    theCol.setCellValueFactory(cellData -> cellData.getValue().selectedInGridProperty()); 
    theCol.setCellFactory(new Callback<TableColumn<GeneratedPersistableBeanFX, Boolean>, TableCell<GeneratedPersistableBeanFX, Boolean>>() { 
     @Override 
     public TableCell<GeneratedPersistableBeanFX, Boolean> call(TableColumn<GeneratedPersistableBeanFX, Boolean> col) { 

      final TableCell<GeneratedPersistableBeanFX, Boolean> cell = new TableCell<GeneratedPersistableBeanFX, Boolean>() { 

       @Override 
       public void updateItem(Boolean item, boolean empty) { 
        super.updateItem(item, empty); 
        setText(null); 
        // setMinHeight(40); 
        if (item == null) { 
         setGraphic(null); 
        } 
        else { 
         if (item.booleanValue() && getGraphic() == null) { 
          setGraphic(CustomImageLoaderFX.getInstance().getImageView("check.png", 16)); 
         } 
         else if (item.booleanValue() && getGraphic() != null) { 
          getGraphic().setVisible(true); 
         } 
         else if (getGraphic() != null) { 
          getGraphic().setVisible(false); 
         } 
         if (getTableView() != null && getTableRow() != null && item != null) { 
          getTableView().fireEvent(
            new CustomTableColumnSelectionChangedEvent((GeneratedPersistableBeanFX) getTableRow().getItem(), item.booleanValue())); 
         } 
        } 
       } 
      }; 

      cell.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() { 
       @Override 
       public void handle(MouseEvent event) { 
        ObservableValue<Boolean> ov = ((TableCell<GeneratedPersistableBeanFX, Boolean>) event.getSource()).getTableColumn() 
          .getCellObservableValue(((TableCell<GeneratedPersistableBeanFX, Boolean>) event.getSource()).getIndex()); 
        SimpleBooleanProperty sp = (SimpleBooleanProperty) ov; 
        if (sp == null) { 
         return; 
        } 
        GeneratedPersistableBeanFX bean = (GeneratedPersistableBeanFX) ((TableCell<GeneratedPersistableBeanFX, Boolean>) event.getSource()) 
          .getTableRow().getItem(); 
        if (sp.getValue() == false) { 
         sp.setValue(true); 
        } 
        else { 
         sp.setValue(false); 
        } 
       } 
      }); 
      return cell; 
     } 

    }); 
    return theCol; 
} 

public static CheckBox getSelectAllCheckBox() { 
    if (select_all == null) { 
     select_all = new CheckBox(); 
     select_all.setOnAction(e -> selectAllBoxes(e)); 
    } 
    return select_all; 
} 

private static void selectAllBoxes(ActionEvent e) { 
    CustomTableView<GeneratedPersistableBeanFX> table = getTableViewFromCheckBox(((CheckBox) e.getSource()).getParent()); 
    ObservableList<GeneratedPersistableBeanFX> items = table.getItems(); 
    for (GeneratedPersistableBeanFX item : items) { 
     item.setSelectedInGrid(((CheckBox) e.getSource()).isSelected()); 
     //What I tried to force to trigger updateItem on all rows 
     table.getColumns().get(0).setVisible(false); 
     table.getColumns().get(0).setVisible(true); 
    } 
} 

@SuppressWarnings("unchecked") 
private static CustomTableView<GeneratedPersistableBeanFX> getTableViewFromCheckBox(Parent parent) { 
    if (parent instanceof CustomTableView<?>) { 
     return (CustomTableView<GeneratedPersistableBeanFX>) parent; 
    } 
    else if (parent != null && parent.getParent() != null) { 
     return getTableViewFromCheckBox(parent.getParent()); 
    } 
    else { 
     return null; 
    } 
} 

例如我有一個對話框,其中顯示材料的3D模型並設有與所有材料的tableview嵌入一個JME 3D窗口。當我點擊選擇所有隻有在桌面視圖視窗中可見的材料在我的3D中被突出顯示時,當我向下滾動時,它有一個有趣的行爲,當我向下滾動時,其餘材料會突出顯示。

問題是,方法updateItem僅針對當前在TableViews視口中可見的單元格調用。

有沒有什麼辦法可以規避這種行爲,並且無論可視性如何,都會調用列表中每個項目的每個單元格?

+1

發佈您的'GeneratedPersistableBeanFX'類(至少與'selectedInGridProperty'相關的部分)。 –

+0

完成,儘管我真的認爲它只是javafx行爲而不是代碼。在其他的tableviews中,我們也會注意到這種行爲,我們會用css在表格中對一些材質着色。如果最後一行只有1/2可見,則最後一行不會着色。必須調整tableview的大小,以便行完美匹配。儘管這可能是一個CSS,這裏它的嚴格的價值相關。 – 404KnowledgeNotFound

回答

0

所以我讀了關於這個問題了一下,發現我有問題,是因爲一個TableView中除其他外,採用虛擬化的細胞,這是解釋的更好here.

基本上一個永遠不應該使用的updateItem方法做任何與邏輯有關的事情,它只是建議改變單元格的視覺效果。

考慮到這一點,我簡單地移動了將updateItem方法中的事件觸發到單擊select all複選框或單擊單元格本身的用戶事件時的時刻。它不夠整潔,但它的工作原理。

private static void selectAllBoxes(ActionEvent e) { 
    CustomTableView<GeneratedPersistableBeanFX> table = getTableViewFromCheckBox(((CheckBox) e.getSource()).getParent()); 
    if (table == null) { 
     return; 
    } 
    ObservableList<GeneratedPersistableBeanFX> items = table.getItems(); 
    for (GeneratedPersistableBeanFX item : items) { 
     item.setSelectedInGrid(((CheckBox) e.getSource()).isSelected()); 
     table.fireEvent(new CustomTableColumnSelectionChangedEvent(item, ((CheckBox) e.getSource()).isSelected())); 
    } 
} 
cell.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() { 
    @SuppressWarnings("unchecked") 
    @Override 
    public void handle(MouseEvent event) { 
     SimpleBooleanProperty sp = (SimpleBooleanProperty) (((TableCell<GeneratedPersistableBeanFX, Boolean>) event.getSource()) 
      .getTableColumn().getCellObservableValue(((TableCell<GeneratedPersistableBeanFX, Boolean>) event.getSource()).getIndex())); 
     if (sp == null) { 
      return; 
     } 
     if (sp.getValue() == false) { 
      sp.setValue(true); 
     } 
     else { 
      sp.setValue(false); 
     } 
     ((TableCell<GeneratedPersistableBeanFX, Boolean>) event.getSource()).getTableView().fireEvent(
      new CustomTableColumnSelectionChangedEvent((GeneratedPersistableBeanFX) ((TableCell<GeneratedPersistableBeanFX, Boolean>) event 
      .getSource()).getTableRow().getItem(), sp.getValue().booleanValue())); 

    } 
}); 

遠離編碼和工作的週末有時可以創造奇蹟!我根本沒有意識到這一點在神父。