Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Javafx adding row dynamically duplicates data

I have a Tableview in Javafx in which I’m trying to add a row dynamically when user presses a button. The problem is that when doing it the previous data in the table gets duplicated. I must say that if I print the size of the items in the table, it returns the correct size, without the duplciates and that I can’t select the duplicated items nor scroll to see them all.
Here is my code:
detail.fxml

<TableView fx:id="tblPersonalExterno" prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
                                            <columns>
                                                <TableColumn prefWidth="781.0000244379044">
                                                    <graphic>
                                                        <Label text="Externo" />
                                                    </graphic>
                                                    <columns>
                                                        <TableColumn fx:id="tblcNombreExterno" prefWidth="270" text="Nombre"/>
                                                        <TableColumn fx:id="tblcEmpresaExterno" prefWidth="270" text="Empresa" />
                                                        <TableColumn fx:id="tblcInfPRLExterno" minWidth="0.0" prefWidth="59.0">
                                                            <graphic>
                                                                <Label text="Inf. PRL">
                                                                    <tooltip>
                                                                        <Tooltip text="Informado PRL" />
                                                                    </tooltip>
                                                                </Label>
                                                            </graphic>
                                                        </TableColumn>
                                                        <TableColumn fx:id="tblcAprobadoPRLExterno" minWidth="0.0" prefWidth="73.00003051757812">
                                                            <graphic>
                                                                <Label text="Apr. Cl. PRL">
                                                                    <tooltip>
                                                                        <Tooltip text="Aprobado cliente PRL" />
                                                                    </tooltip>
                                                                </Label>
                                                            </graphic>
                                                        </TableColumn>
                                                        <TableColumn fx:id="tblcFechaAprPRLExterno" prefWidth="100.0">
                                                            <graphic>
                                                                <Label text="Fecha apr.">
                                                                    <tooltip>
                                                                        <Tooltip text="Fecha de aprobación" />
                                                                    </tooltip>
                                                                </Label>
                                                            </graphic>
                                                        </TableColumn>
                                                        <TableColumn prefWidth="60.0" text="Validez PRL">
                                                            <columns>
                                                                <TableColumn fx:id="tblcFechaDesdePRLExterno"  prefWidth="100.0" text="Desde" />
                                                                <TableColumn fx:id="tblcFechaHastaPRLExterno" prefWidth="100.0" text="Hasta" />
                                                            </columns>
                                                        </TableColumn>
                                                    </columns>
                                                </TableColumn>
                                            </columns>
                                        </TableView>
<ToolBar prefHeight="40.0" prefWidth="200.0">
                                            <items>
                                                <Button fx:id="btnAñadirExterno" mnemonicParsing="false" onAction="#addExterno">
                                                    <graphic>
                                                        <FontIcon iconLiteral="mdi-account-plus"
                                                            iconSize="16" />
                                                    </graphic>
                                                    <tooltip>
                                                        <Tooltip text="Añadir Personal Externo" />
                                                    </tooltip>
                                                </Button>
                                                <Button fx:id="btnEliminarExterno" mnemonicParsing="false">
                                                    <graphic>
                                                        <FontIcon iconLiteral="mdi-delete-forever"
                                                            iconSize="16" />
                                                    </graphic>
                                                    <tooltip>
                                                        <Tooltip text="Eliminar Personal Externo" />
                                                    </tooltip>
                                                </Button>
                                            </items>
                                        </ToolBar>

DetailsController.java

public class DetailsController {
    private ObservableList<Responsable> listaPersonalExterno = FXCollections.observableArrayList();
    @FXML
    private TableView<Responsable> tblPersonalExterno;
    @FXML
    private TableColumn<Responsable, String> tblcNombreExterno;
    @FXML
    private TableColumn<Responsable, String> tblcEmpresaExterno;
    @FXML
    private TableColumn<Responsable, Boolean> tblcInfPRLExterno;
    @FXML
    private TableColumn<Responsable, Boolean> tblcAprobadoPRLExterno;
    @FXML
    private TableColumn<Responsable, LocalDate> tblcFechaAprPRLExterno;
    @FXML
    private TableColumn<Responsable, LocalDate> tblcFechaDesdePRLExterno;
    @FXML
    private TableColumn<Responsable, LocalDate> tblcFechaHastaPRLExterno;
    
    public DetailsController() {
        cargarPersonalExterno();
    }
    public ObservableList<Responsable> listaPersonalExterno(){
        return listaPersonalExterno;
    }
    
    @FXML
    public void initialize() {
        doBindTablaPersonalExterno();
    }
    
    private void doBindTablaPersonalExterno() {
        tblcNombreExterno.setCellValueFactory(new PropertyValueFactory<Responsable, String>("nombre"));
        tblcNombreExterno.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("");
                    }else {
                        TextField tf = new TextField();
                        tf.setText(item);
                        setGraphic(tf);
                    }
                }
            };
            return cell;
        });
        tblcEmpresaExterno.setCellValueFactory(new PropertyValueFactory<Responsable, String>("empresa"));
        tblcEmpresaExterno.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("");
                    }else {
                        TextField tf = new TextField();
                        tf.setText(item);
                        setGraphic(tf);
                    }
                }
            };
            return cell;
        });
        tblcInfPRLExterno.setCellValueFactory(cellData -> new SimpleBooleanProperty(cellData.getValue().getPrl().isInformado()));
        tblcInfPRLExterno.setCellFactory(col -> {
            TableCell<Responsable, Boolean> cell = new TableCell<Responsable, Boolean>(){
                @Override
                public void updateItem(Boolean item, boolean empty) {
                    super.updateItem(item, empty);
                    if(empty) {
                        setText("");
                    }else {
                        CheckBox chk = new CheckBox();
                        setStyle("-fx-alignment: CENTER;");
                        if(item != null) {
                            chk.setSelected(item);
                        }
                        setGraphic(chk);
                    }
                }
            };
            return cell;
        });
        tblcAprobadoPRLExterno.setCellValueFactory(cellData -> new SimpleBooleanProperty(cellData.getValue().getPrl().isAprobado()));
        tblcAprobadoPRLExterno.setCellFactory(col -> {
            TableCell<Responsable, Boolean> cell = new TableCell<Responsable, Boolean>(){
                @Override
                public void updateItem(Boolean item, boolean empty) {
                    super.updateItem(item, empty);
                    if(empty) {
                        setText("");
                    }else {
                        CheckBox chk = new CheckBox();
                        setStyle("-fx-alignment: CENTER;");
                        if(item != null) {
                            chk.setSelected(item);
                        }
                        setGraphic(chk);
                    }
                }
            };
            return cell;
        });
        tblcFechaAprPRLExterno.setCellValueFactory(cellData -> new SimpleObjectProperty<LocalDate>(cellData.getValue().getPrl().getFechaAprobacion()));
        tblcFechaAprPRLExterno.setCellFactory(col -> {
            TableCell<Responsable, LocalDate> cell = new TableCell<Responsable, LocalDate>(){
                @Override
                public void updateItem(LocalDate item, boolean empty) {
                    super.updateItem(item, empty);
                    if(empty) {
                        setText("");
                    }else {
                        DatePicker dp = new DatePicker();
                        setStyle("-fx-alignment: CENTER;");
                        dp.setValue(item);
                        setGraphic(dp);
                    }
                }
            };
            return cell;
        });
        
        tblcFechaDesdePRLExterno.setCellValueFactory(cellData -> new SimpleObjectProperty<LocalDate>(cellData.getValue().getPrl().getValidez().getInicio()));
        tblcFechaDesdePRLExterno.setCellFactory(col -> {
            TableCell<Responsable, LocalDate> cell = new TableCell<Responsable, LocalDate>(){
                @Override
                public void updateItem(LocalDate item, boolean empty) {
                    super.updateItem(item, empty);
                    if(empty) {
                        setText("");
                    }else {
                        DatePicker dp = new DatePicker();
                        setStyle("-fx-alignment: CENTER;");
                        dp.setValue(item);
                        setGraphic(dp);
                    }
                }
            };
            return cell;
        });
        
        tblcFechaHastaPRLExterno.setCellValueFactory(cellData -> new SimpleObjectProperty<LocalDate>(cellData.getValue().getPrl().getValidez().getInicio()));
        tblcFechaHastaPRLExterno.setCellFactory(col -> {
            TableCell<Responsable, LocalDate> cell = new TableCell<Responsable, LocalDate>(){
                @Override
                public void updateItem(LocalDate item, boolean empty) {
                    super.updateItem(item, empty);
                    if(empty) {
                        setText("");
                    }else {
                        DatePicker dp = new DatePicker();
                        setStyle("-fx-alignment: CENTER;");
                        dp.setValue(item);
                        setGraphic(dp);
                    }
                }
            };
            return cell;
        });
    }
        
    /**
     * Carga el personal externo
     */
    private void cargarPersonalExterno() {
        List<Responsable> lista = new ArrayList<Responsable>();
        Responsable r1 = new Responsable();
        r1.setNombre("NEUS");
        Responsable r2 = new Responsable();
        r2.setNombre("PEPE");
        lista.add(r1);
        lista.add(r2);
        listaPersonalExterno.addAll(lista);
    }
        
    @FXML
    public void addExterno() {
        Responsable r = new Responsable();
        listaPersonalExterno.add(r);
    }
    
}

Here is an image of the behaviour. The duplicated rows under the blank one seem to not exists because I can’t select them, can’t scroll and can’t access to them by code.
Screenshot

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

The problem with your code is when your item is empty or null, you are only setting the text to null but not the graphic. So the graphic part will still stay in the cell when the row/cell is reused.

Reset both the text and graphic when the item is empty in all your cell factories. And also it is a bad idea to create new nodes in the updateItem method. Create the DatePicker per cell instance and set it as graphic in the updateItem. Something like :

tblcFechaDesdePRLExterno.setCellFactory(col -> {
            TableCell<Responsable, LocalDate> cell = new TableCell<Responsable, LocalDate>(){
               private DatePicker dp = new DatePicker();
               @Override
                public void updateItem(LocalDate item, boolean empty) {
                    super.updateItem(item, empty);
                    if(empty) {
                        setText(null);
                        setGraphic(null); // THIS IS MISSING IN YOUR CODE
                    }else {
                        setStyle("-fx-alignment: CENTER;");
                        dp.setValue(item);
                        setGraphic(dp);
                    }
                }
            };
            return cell;
        });
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading