TableView Cell updateItem未在视口

时间:2017-02-17 10:54:06

标签: java javafx tableview

我已经创建了自己的选择列,并且在列标题中我有一个复选框,当我点击时更改我为cellValueFactory设置的单元格的值,该单元格触发了TableCell中触发自定义事件的方法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;
    }
}   

例如,我在对话框中嵌入了一个JME 3D窗口,其中显示了材料的3D模型,还有一个包含所有材料的工作台视图。当我点击选择全部时,只有在tableview视口中可见的材料正在我的3D中突出显示,当我向下滚动时,它有一个有趣的行为,当我向下滚动时剩余的材料会突出显示。

问题是,方法updateItem仅针对TableViews视口中当前可见的单元格调用。

有没有办法绕过这种行为并让它调用列表中每个项目的每个单元格而不管可见性?

1 个答案:

答案 0 :(得分: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()));

    }
});

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