如何使 TextFieldTableCell 以模型 属性 为条件?

How to make TextFieldTableCell conditional on model property?

我有一个 TableView 和一个可编辑的 TextFieldTableCell,我想根据我的模型对象的 BooleanProperty 限制它的可用性。

例如,textField.disableProperty().bind(item.editableProperty().not())

目前,我有来自 Oracle 文档的基本实现:

colComment.setCellFactory(TextFieldTableCell.forTableColumn());
colComment.setOnEditCommit(event -> event.getTableView().getItems().get(
    event.getTablePosition().getRow()).setComment(
    event.getNewValue())
);

这显然不允许有太大的灵活性。目的是检查项目的 editableProperty,如果是 true,则显示 TextFieldTableCell 并将其绑定到项目的 commentProperty.

如果 属性 是 false,单元格应该只显示 commentProperty.

的值

我过去没有使用过可编辑的 TableView,所以我有点迷茫。

我试图通过自己手动设置图形来破解变通方法,但这对单元格没有任何作用:

colComment.setCellFactory(cell -> new TableCell<LogEntry, String>() {

    final TextField txtComment = new TextField();

    @Override
    protected void updateItem(String item, boolean empty) {

        super.updateItem(item, empty);

        if (item == null || empty) {
            setGraphic(null);
        } else {
            LogEntry logEntry = (LogEntry) getTableRow().getItem();
            if (logEntry.isEditable()) {
                txtComment.textProperty().bindBidirectional(logEntry.commentProperty());
                setGraphic(txtComment);
            } else {
                setText(item);
            }
         }
     }
 });

基本方法是根据条件禁止单元格编辑。 TextFieldTableCell 对此没有直接支持,但可以像任何其他类型的单元格一样进行扩展。选项是

  • 如果不满足条件,则重写 startEdit 不执行任何操作
  • 将单元格的可编辑性属性绑定到 rowItem
  • 的条件

最简单的是第一个(后者有点复杂,因为需要在父 TableRow 及其项更改时进行更新)。一个简单的例子(除单元格外的所有样板;):

public class TableCellConditionalEditable extends Application {
    
    /**
     * Cell with custom condition to prevent editing.
     */
    public static class ConditionalEditableCell extends TextFieldTableCell<ConditionalWritable, String> {
        
        public ConditionalEditableCell() {
            super(new DefaultStringConverter());
        }

        /** 
         * Overridden to do nothing if rowItem-related condition not met.
         */
        @Override
        public void startEdit() {
            if (!isConditionalEditable()) return;
            super.startEdit();
        }

       private boolean isConditionalEditable() {
            if (getTableRow() == null || getTableRow().getItem() == null || isEmpty()) return false;
            return getTableRow().getItem().writableProperty().get();
        }
        
    }
    
    private Parent createContent() {
        TableView<ConditionalWritable> table = new TableView<>(ConditionalWritable.conditionalWritables());
        TableColumn<ConditionalWritable, String> text = new TableColumn<>("Text");
        text.setCellValueFactory(cc -> cc.getValue().textProperty());
        TableColumn<ConditionalWritable, Boolean> writable = new TableColumn<>("Writable");
        writable.setCellValueFactory(cc -> cc.getValue().writableProperty());
        table.getColumns().addAll(text, writable);
        
        table.setEditable(true);
        text.setCellFactory(cc -> new ConditionalEditableCell());
        
        BorderPane content = new BorderPane(table);
        return content;
    }

    @Override
    public void start(Stage stage) throws Exception {
        stage.setScene(new Scene(createContent()));
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

    public static class ConditionalWritable {
        
        private SimpleStringProperty text;
        private SimpleBooleanProperty writable;

        public ConditionalWritable(String text, boolean writable) {
            this.text = new SimpleStringProperty(text);
            this.writable = new SimpleBooleanProperty(writable);
        }
        
        public StringProperty textProperty() {
            return text;
        }
        
        public BooleanProperty writableProperty() {
            return writable;
        }
        
        public static ObservableList<ConditionalWritable> conditionalWritables() {
            return FXCollections.observableArrayList(
                    new ConditionalWritable("some data", false),  
                    new ConditionalWritable("other data", true),  
                    new ConditionalWritable("nothing important", true)  
                    );
        }
    }
    
}