Domanda

I've developed a simple custom TableCell to enable the edition of the values in a table. The behaviour of the component is show a BigDecimalTextField no matter if the user is editing or not that cell, it should enable the edition all the time. The component is working fine, there is only a strange problem: when the table is rendered, instead of show only a single line, three lines are shown:

Rendering three times

The code of the component is this:

public class BigDecimalEditingCell extends TableCell {

    private BigDecimalField spinner = new BigDecimalField(new BigDecimal("0.00"));
    private ObjectProperty<BigDecimal> campoLigado = null;

    public BigDecimalEditingCell() {
        this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
        createField();
    }

    private void createField() {
        spinner.setStepwidth(new BigDecimal("0.01"));
        spinner.setMinValue(new BigDecimal("0.00"));
        spinner.setFormat(NumberFormat.getInstance());
        spinner.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
    }

    @Override
    public void updateItem(Object item, boolean empty) {
        super.updateItem(item, empty);
        criarBind();
        setGraphic(spinner);
        setText(null);
    }

    private void criarBind() {
        ObservableValue<BigDecimal> valor = getTableColumn().getCellObservableValue(getIndex());
        if (valor != null) {
            ObjectProperty<BigDecimal> propriedade = (ObjectProperty<BigDecimal>) valor;
            if (campoLigado == null) {
                spinner.numberProperty().bindBidirectional(propriedade);
                campoLigado = propriedade;
            } else if (campoLigado != propriedade) {
                spinner.numberProperty().unbindBidirectional(campoLigado);
                spinner.numberProperty().bindBidirectional(propriedade);
                campoLigado = propriedade;
            }
        }
    }    
}

If I use the default TextFieldTableCell, the table is rendered correctly. I have another component (like this) that uses JavaFX's DatePicker and the same problem happens. What I'm doing wrong?

ADDED

Here is the usage of this component:

public class ControladorPainelFormaPagamento extends ControladorPainelSubmeter {

    @FXML
    private TableView<ParcelaBean> tabela;
    @FXML
    private TableColumn<ParcelaBean, LocalDate> colunaVencimento;
    @FXML
    private TableColumn<ParcelaBean, BigDecimal> colunaValor;
    private FormaPagamentoBean bean;

    .
    .
    .

    private void configurarColunaValor() {
        colunaValor.setCellValueFactory(new PropertyValueFactory<ParcelaBean, BigDecimal>("valor"));
        colunaValor.setCellFactory(new Callback<TableColumn<ParcelaBean, BigDecimal>, TableCell<ParcelaBean, BigDecimal>>() {
            @Override
            public TableCell<ParcelaBean, BigDecimal> call(TableColumn<ParcelaBean, BigDecimal> parcelaBeanStringTableColumn) {
                return new BigDecimalEditingCell();
            }
        });
    }

    private void configurarColunaVencimento() {
        colunaVencimento.setCellValueFactory(new PropertyValueFactory<ParcelaBean, LocalDate>("dataVencimento"));
    }

    public void carregar(ModoExibicao modoExibicao, FormaPagamentoBean formaPagamento) {
        this.bean=formaPagamento;
        tabela.setItems(bean.getParcelas());
        .
        .
        .
    }

    .
    .
    .

}

I've checked, inclusive using debug, if there was more than one bean in the list used by the table. Every time only one was there.

È stato utile?

Soluzione

I was looking at another table in the same system and noticed this: when there is no item in the table, no one row is rendered. empty table

but when you add just one row, the table renders empty row until reach the height of the table (repair the light grey rows):

table with a row

So, it was obvious that the extra rows were added by TableView, this way a simple null check solve the problem:

public class BigDecimalEditingCell extends TableCell {

    private BigDecimalField element = new BigDecimalField(new BigDecimal("0.00"));
    private ObjectProperty<BigDecimal> campoLigado = null;

    @Override
    protected void updateItem(Object item, boolean empty) {
        super.updateItem(item,empty);
        if (getIndex() < getTableView().getItems().size() && !empty) {
            createField();
            createBind();
            setGraphic(element);
            setText(null);
        } else {
            removeBind();
            setGraphic(null);
        }
    }

    .
    .
    .
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top