我有一个TextField和一个ListView。当用户在TextField中键入时,ListView中会出现建议:
当TextField为空时,ListView会通过将visible和managed属性设置为false来消失。
但是,当用户开始输入时,ListView会占用空间并将所有内容都按下。使用.setManaged(false)允许它不占用任何空间,但它不再显示,因为我还没有为它定义一个位置。我已经尝试设置搜索列表的layoutX和layoutY,但它仍然没有显示。
理想情况下,我希望ListView的位置受到布局的影响,但不占用任何空间。
有什么想法吗?
答案 0 :(得分:0)
将包含文本字段的容器包装在AnchorPane
中。在文本字段容器之后将ListView
添加到AnchorPane
(因此它保持在顶部)。然后,当您使文本字段可见时,您需要相对于文本字段正确定位ListView
;我认为最好的方法是首先将文本字段的边界从本地坐标转换为Scene
坐标,然后将这些边界转换为相对于AnchorPane
的坐标。
这是一个SSCCE:
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.geometry.Bounds;
import javafx.geometry.Insets;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
public class SuggestionList extends Application {
@Override
public void start(Stage primaryStage) {
AnchorPane root = new AnchorPane();
ListView<String> suggestionBox = new ListView<>();
suggestionBox.getItems().addAll("Here", "Are", "Some", "Suggestions");
suggestionBox.setMaxHeight(100);
suggestionBox.setVisible(false);
// Grid pane to hold a bunch of text fields:
GridPane form = new GridPane();
for (int i=0; i<10; i++) {
form.addRow(i, new Label("Enter Text:"), createTextField(suggestionBox));
}
// just move the grid pane a little to test suggestion box positioning:
AnchorPane.setLeftAnchor(form, 20.0);
AnchorPane.setRightAnchor(form, 20.0);
AnchorPane.setTopAnchor(form, 20.0);
AnchorPane.setBottomAnchor(form, 20.0);
// allows focus on grid pane, so user can click on it to remove focus from text field.
form.setFocusTraversable(true);
root.setPadding(new Insets(20));
root.getChildren().addAll(form, suggestionBox);
Scene scene = new Scene(root, 600, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
private TextField createTextField(ListView<String> suggestionBox) {
TextField textField = new TextField();
ChangeListener<String> selectionListener = (obs, oldItem, newItem) -> {
if (newItem != null) {
textField.setText(newItem);
}
};
textField.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
if (isNowFocused) {
suggestionBox.setVisible(true);
// compute bounds of text field relative to suggestion box's parent:
Parent parent = suggestionBox.getParent(); // (actually the anchor pane)
Bounds tfBounds = textField.getBoundsInLocal();
Bounds tfBoundsInScene = textField.localToScene(tfBounds);
Bounds tfBoundsInParent = parent.sceneToLocal(tfBoundsInScene);
// position suggestion box:
suggestionBox.setLayoutX(tfBoundsInParent.getMinX());
suggestionBox.setLayoutY(tfBoundsInParent.getMaxY());
suggestionBox.setPrefWidth(tfBoundsInParent.getWidth());
suggestionBox.getSelectionModel().selectedItemProperty().addListener(selectionListener);
} else {
suggestionBox.setVisible(false);
suggestionBox.getSelectionModel().selectedItemProperty().removeListener(selectionListener);
}
});
textField.setOnAction(event -> {
suggestionBox.setVisible(false);
suggestionBox.getSelectionModel().selectedItemProperty().removeListener(selectionListener);
});
return textField ;
}
public static void main(String[] args) {
launch(args);
}
}
您可以使用类似的位置技巧,只需将其添加到同一场景,managed
设置为false。