在同一位置用 javafx 中的文本字段替换标签

Replace a label with textfield in javafx at same position

我的 VBox 中有许多标签,单击一个按钮我想用文本字段替换所有这些标签。

您可以遍历 VBox 并替换:

VBox vBox = ...
int currentPos = 0;
Map<Integer, TextField> toInsert = new HashMap<>(); // map with TextFields that need to be inserted at position
for (Iterator<Node> iterator = vBox.getChildren().iterator(); iterator.hasNext(); ) {
    Node child = iterator.next();
    if (child instanceof Label) {
        Label lbl = (Label)child;
        TextField text = new TextField(lbl.getText());
        iterator.remove(); // remove the label that is at index currentPos
        toInsert.put(currentPos, text);

    }
    currentPos++;
}
for (Integer pos : toInsert.keySet()) {
    TextField field = toInsert.get(pos);
    vBox.getChildren().add(pos, field); // Add the Text field at the old position of the Label
}

在第一个循环中,您删除标签并创建替换 TextFields 并记住稍后需要插入它们的位置。这不能发生在同一个循环中。然后在第二个循环中,将这些 TextField 添加到 VBox 中您指定的位置。

编辑: 根据@fabian 的有效评论,上述建议的解决方案可能会导致问题。这是另一种方法,它创建第二个 VBox,其中复制所有非 Label 节点,并将 Label 替换为 TextField。我假设原来的 VBox 是某些 Parent.

的子元素
Parent parent = ... // Parent of VBox
VBox vbox = ...
// Find the index of vBox in Parent
int position = 0;
for (int i = 0; i<parent.getChildren().size(); i++) {
    if (parent.getChildren().equals(vBox)) {
        position = i;
        break; // found our position, no need to look further
    }
}
VBox copyVBox = new VBox();
for (Node child : vBox.getChildren()) {
    if (child instanceof Label) {
        Label lbl = (Label)child;
        TextField text = new TextField(lbl.getText());
        copyVBox.getChildren().add(text);        
    } else {
        copyVBox.getChildren().add(child);
    }
}
parent.getChildren().remove(vBox);
parent.getChildren().add(position, copyVBox);

我不建议使用 VBox,因为替换 children 可能会修改布局,从而导致用户感到困惑。
相反,我建议使用 GridPane,它允许您在单个单元格中放置多个 children。这样你就可以把所有的 Labels 和 VBoxes 放在网格中,但是将 TextFields 的 visible 属性 设置为 false.这意味着 LabelTextField 都将用于布局计算,您可以通过反转 visible 属性 在 "editing mode" 和 "normal mode" 之间简单地交换所有 children:

FXML

<HBox xmlns:fx="http://javafx.com/fxml/1" fx:controller="fxml.LabelReplaceController">
    <children>
        <GridPane fx:id="grid">
            <children>
                <TextField fx:id="t1" text="Hello World!" visible="false" GridPane.rowIndex="0"/>
                <Label text="${t1.text}" GridPane.rowIndex="0" />
                <TextField fx:id="t2" text="foo" visible="false" GridPane.rowIndex="1"/>
                <Label text="${t2.text}" GridPane.rowIndex="1" />
                <TextField fx:id="t3" text="bar" visible="false" GridPane.rowIndex="2"/>
                <Label text="${t3.text}" GridPane.rowIndex="2" />
            </children>
        </GridPane>
        <ToggleButton selected="false" onAction="#selectionChanged" text="edit"/>
    </children>
</HBox>
public class LabelReplaceController {

    @FXML
    private Pane grid;

    @FXML
    private void selectionChanged(ActionEvent event) {
        for (Node child : grid.getChildren()) {
            child.setVisible(!child.isVisible());
        }
    }

}