Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
868 views
in Technique[技术] by (71.8m points)

javafx - How to make TextFieldTableCell conditional on model property?

I have a TableView with an editable TextFieldTableCell that I want to restrict to be available based on a BooleanProperty of my model object.

For example, textField.disableProperty().bind(item.editableProperty().not())

Currently, I have the basic implementation from the Oracle docs:

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

This obviously does not allow much flexibility. The desire is to check the item's editableProperty and if it is true, display the TextFieldTableCell and bind it to the item's commentProperty.

If that property is false, the cell should simply display the value of the commentProperty.

I have not worked with editable TableViews in the past so I am a bit lost.

I have tried to hack out a workaround with manually setting the graphic myself, but that just does nothing with the cell:

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);
            }
         }
     }
 });
question from:https://stackoverflow.com/questions/65947317/how-to-make-textfieldtablecell-conditional-on-model-property

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The basic approach is to disallow cell's editing based on a condition. TextFieldTableCell has no direct support for such, but can be extended just as any other type of cell. Options are

  • override startEdit to do nothing if the condition is not met
  • bind the cell's editability property to a condition of the rowItem

The most simple is the first (the latter is a bit more involved, due to requiring updates when parent TableRow and its item changes). A quick example (all boiler-plate except the cell ;):

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)  
                    );
        }
    }
    
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...