2017-02-17 82 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())); 

    } 
}); 

远离编码和工作的周末有时可以创造奇迹!我根本没有意识到这一点在神父。