tableview - 是否可以在 JavaFX8 中逐行禁用可编辑的表列?

标签 tableview javafx-8 tablecolumn

我有一个用例,我认为它是非常标准的,但是我还没有找到关于如何执行此操作或是否可能的示例。

假设我有以下 TableView

First Name    Last Name    Street    NewRecord

Tom           Smith        Main St.     Yes
Mike          Smith        First St.    No

在这种情况下,网格的前三个单元格应该是可编辑的,因为记录是新的,但是当记录不是新的时,则应禁用姓氏单元格。

我在 CellFactory 和 RowFactory 中尝试过这一点 - 但还没有找到实现此目的的方法。

感谢您的帮助。

最佳答案

最简单的方法是使用第三方绑定(bind)库:ReactFX 2.0 内置了此功能,如 here 中所述。 。使用它你可以做到

TableColumn<Person, String> lastNameColumn = new TableColumn<>("Last Name");
lastNameColumn.setEditable(true);
lastNameColumn.setCellFactory(tc -> {
    TableCell<Person, String> cell = new TextFieldTableCell<>();
    cell.editableProperty().bind(
        // horrible cast needed because TableCell.tableRowProperty inexplicably returns a raw type:
        Val.flatMap(cell.tableRowProperty(), row -> (ObservableValue<Person>)row.itemProperty())
           .flatMap(Person::newRecordProperty)
           .orElseConst(false));
    return cell ;
});

(假设一个 Person 表模型对象具有明显的 JavaFX 属性和方法)。

如果没有库,您需要一个非常悲惨的嵌套监听器列表:

TableColumn<Person, String> lastNameColumn = new TableColumn<>("Last Name");
lastNameColumn.setEditable(true);
lastNameColumn.setCellFactory(tc -> {
    TableCell<Person, String> cell = new TextFieldTableCell<>();
    ChangeListener<Boolean> newRecordListener = (obs, wasNewRecord, isNewRecord) -> updateEditability(cell);
    ChangeListener<Person> rowItemListener = (obs, oldPerson, newPerson) -> {
        if (oldPerson != null) {
            oldPerson.newRecordProperty().removeListener(newRecordListener);
        }
        if (newPerson != null) {
            newPerson.newRecordProperty().addListener(newRecordListener);
        }
        updateEditability(cell);
    };
    ChangeListener<TableRow> rowListener = (obs, oldRow, newRow) -> {
        if (oldRow != null) {
            ((ObservableValue<Person>)oldRow.itemProperty()).removeListener(rowItemListener);
            if (oldRow.getItem() != null) {
                ((Person)oldRow.getItem()).newRecordProperty().removeListener(newRecordListener);
            }
        }
        if (newRow != null) {
            ((ObservableValue<Person>)newRow.itemProperty()).addListener(rowItemListener);
            if (newRow.getItem() != null) {
                ((Person)newRow.getItem()).newRecordProperty().addListener(newRecordListener);
            }
        }
        updateEditability(cell);
    };
    cell.tableRowProperty().addListener(rowListener);
    return cell ;
});

然后

private void updateEditability(TableCell<Person, String> cell) {
    if (cell.getTableRow() == null) {
        cell.setEditable(false);
    } else {
        TableRow<Person> row = (TableRow<Person>) cell.getTableRow();
        if (row.getItem() == null) {
            cell.setEditable(false);
        } else {
            cell.setEditable(row.getItem().isNewRecord());
        }
    }
}

使用“传统风格”API 的替代方案是

TableColumn<Person, String> lastNameColumn = new TableColumn<>("Last Name");
lastNameColumn.setEditable(true);
lastNameColumn.setCellFactory(tc -> {
    TableCell<Person, String> cell = new TextFieldTableCell<>();
    cell.editableProperty().bind(
        Bindings.selectBoolean(cell.tableRowProperty(), "item", "newRecord"));
    return cell ;
});

我不喜欢这个选项,因为它缺乏任何类型安全(或者实际上根本没有任何编译器检查),此外,在某些早期版本的 JavaFX 中,如果“链”中的任何属性为 null,则会生成几乎无穷无尽的警告消息值(value)观(在这种情况下,他们经常会这样做)。我相信后一个问题已得到解决,但恕我直言,ReactFX 版本要好得多。

关于tableview - 是否可以在 JavaFX8 中逐行禁用可编辑的表列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37010431/

相关文章:

JavaFX:禁用 TableView 多列排序

ios - 如何使表格单元格展开和折叠

java - 在 Alert 上调用 initOwner 时的 NPE (JavaFX)

javafx - 如何使用 JavaFX 为未装饰的舞台添加阴影?

java - 使用JavaFX图表API绘制图表图像

java - 如何在java中从另一个类中删除jTable列

ios - 如何使用 Swift 处理 tableView 单元格音频播放和暂停按钮?

swift - 访问 tableView SWIFT 中的文本字段

java - 删除 JTable 列标识符

php - 在一列中放置多个 MySQL 行