Search code examples
javafxbindingtableviewtextfield

Javafx Textfield in tablerow loses focus after bindBidirectional


I have a tableview with some input controls inside its tablecells which are bind to a model's properties. The problem is that with any change the user mades in textfields, they lose the focus when doing the binding.

tblcNombre.setCellValueFactory(new PropertyValueFactory<Responsable, String>("nombre"));
tblcNombre.setCellFactory(col -> {
    TableCell<Responsable, String> cell = new TableCell<Responsable, String>(){
        @Override
        public void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);
            if(empty) {
                setText("");
                setGraphic(null);
            }else {
                TextField tf = new TextField();
                tf.textProperty().bindBidirectional(getTableRow().getItem().nombreProperty());
                tf.setText(item);
                setGraphic(tf);
            }
        }
    };
    return cell;
});

Any idea on how to solve it? Thank you!

Edit: I think it happens becasue when user changes textfield text, the cell is repainted, so updateItem is called again, and it creates a new textfield with a new binding. But I can't find a solution for it


Solution

  • So, following the comments of jewelsea I finally got into this:

    tblcEmail.setCellValueFactory(data -> data.getValue().emailProperty());
    tblcEmail.setCellFactory(col -> {
        TableCell<Responsable, String> cell = new TableCell<Responsable, String>(){
            TextField tf;
            {
                tf = new TextField();
                tf.focusedProperty().addListener(new ChangeListener<Boolean>(){
                    @Override
                    public void changed(ObservableValue<? extends Boolean> arg0, Boolean oldPropertyValue, Boolean newPropertyValue){
                        if (newPropertyValue){
                            getTableRow().getItem().emailProperty().unbind();
                        }else{
                            //Lost focus.
                            //Bind the data
                            getTableRow().getItem().emailProperty().bind(tf.textProperty());
                        }
                    }
                });
            }
            @Override
            public void updateItem(String item, boolean empty) {
                super.updateItem(item, empty);
                setText("");
                if(empty) {
                    setGraphic(null);
                }else {
                    tf.setText(item);
                    setGraphic(tf);
                }
            }
        };
        return cell;
    });
    

    I'm doing the binding in the focus property of the textfield because updateItem() is called for every line, and it would bind on the same textfield all properties.