在同一位置用 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
}
在第一个循环中,您删除标签并创建替换 TextField
s 并记住稍后需要插入它们的位置。这不能发生在同一个循环中。然后在第二个循环中,将这些 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。这样你就可以把所有的 Label
s 和 VBox
es 放在网格中,但是将 TextField
s 的 visible
属性 设置为 false
.这意味着 Label
和 TextField
都将用于布局计算,您可以通过反转 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());
}
}
}
我的 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
}
在第一个循环中,您删除标签并创建替换 TextField
s 并记住稍后需要插入它们的位置。这不能发生在同一个循环中。然后在第二个循环中,将这些 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。这样你就可以把所有的 Label
s 和 VBox
es 放在网格中,但是将 TextField
s 的 visible
属性 设置为 false
.这意味着 Label
和 TextField
都将用于布局计算,您可以通过反转 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());
}
}
}