Javafx adding row dynamically duplicates data

huangapple go评论57阅读模式
英文:

Javafx adding row dynamically duplicates data

问题

以下是您提供的代码的翻译部分:

<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>
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;
        });
        // 省略其他列的绑定和单元格工厂的设置
    }

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

这是您提供的代码的翻译版本。如果您需要进一步的帮助或有其他问题,请随时提问。

英文:

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

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

DetailsController.java

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

答案1

得分: 5

你的代码问题在于当项目为空或为null时,你只将文本设置为null,但没有设置图形。因此,当行/单元格被重用时,图形部分仍然保留在单元格中。

在所有的单元格工厂中,当项目为空时,重置文本和图形。另外,在updateItem方法中创建新节点是一个不好的主意。应该在每个单元格实例中创建DatePicker,并在updateItem中将其设置为图形,类似于以下代码:

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); // 这在你的代码中缺失了
            } else {
                setStyle("-fx-alignment: CENTER;");
                dp.setValue(item);
                setGraphic(dp);
            }
        }
    };
    return cell;
});
英文:

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 -&gt; {
TableCell&lt;Responsable, LocalDate&gt; cell = new TableCell&lt;Responsable, LocalDate&gt;(){
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(&quot;-fx-alignment: CENTER;&quot;);
dp.setValue(item);
setGraphic(dp);
}
}
};
return cell;
});

huangapple
  • 本文由 发表于 2023年7月17日 15:02:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76702132.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定