当前位置: 首页 > 知识库问答 >
问题:

JavaFX:使节点不占用空间,但让其父节点决定其位置

华建同
2023-03-14

我有一个文本字段和一个列表视图。当用户在文本字段中键入内容时,列表视图中会出现一些建议:

当TextField为空时,通过将可见和托管属性设置为false,ListView将消失。

然而,当用户开始输入时,ListView会占用空间并向下推送所有内容。使用。setManaged(false)允许它不占用任何空间,但它不再显示,因为我还没有为它定义位置。我尝试过设置搜索列表的layoutX和layoutY,但是还是没有显示。

理想情况下,我希望ListView的位置受布局的影响,但不占用任何空间。

有什么想法吗?

共有1个答案

别永年
2023-03-14

将保存文本字段的容器包装在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);
    }
}

您可能能够使用类似的位置技巧,只需将它添加到同一个场景中,并将< code>managed设置为false。

 类似资料:
  • 我有一个XML文档,它包含一个非常复杂(对我来说)的结构,没有换行符。它有许多具有类似结构的元素: 我需要得到节点值的文本,这是节点成员的孩子也有孩子的名字与特定的文本(在这种情况下virtual_size)。也有可能存在几个类似的节点。我可以用[1]etc吗? 这让我知道了节点的名称,但是如何达到“值”节点呢?

  • 我有一个具有必要字段的窗格扩展类。它将是“大门”。 调用控制器从FXML加载节点树,并将其作为子级附加到“gate”对象 然后创建并显示一个以“gate”为根节点的新场景。 新的窗口控制器有一个对FXML根节点(“gate”的直接子节点)的引用,他所需要做的就是在其上使用.getparent()来获取“gate”。 但管他呢!它返回null!我做错了什么?我应该通过FXMLLoader设置一个不同

  • 如何获取此html片段中a的href值? 我需要根据I标记中的类获取它 我试过了,但没有结果

  • 我试图创建一个JavaFX树视图,其中有复选框树项。我要求所有有孩子的节点都应该被禁用。但是这些节点的所有子节点都应该是可单击的。 基本上,如果树项目是一个叶子,它应该被启用和点击。 这是我使用过的当前代码。它禁用了带有子节点的节点,但问题是,由于禁用了它,我无法访问父节点内部的代码。

  • 我有一种情况,我在JavaFX中有一个容器节点(HBox)和两个子节点。当我从左边的子节点拖到右边时,我会得到很多拖到左边节点的事件,最后当我在右边节点上释放鼠标时,我会在父节点中得到一个单击事件。下面是一些复制这种情况的代码。 我想知道的是:如何阻止家长接收此点击事件?我在使用事件的左、右节点上尝试了各种事件过滤器和事件处理程序,但似乎找不到合适的过滤器和事件处理器来防止单击事件发送到父节点。有

  • 如果我没弄错的话,树通常是一个列表,其中的元素按特定顺序排列。孩子们不在他们自己的子列表中,他们都在同一个列表中。 所以,我试图创建一个Tree类,其中包含TreeNodes(类)使用Tree类中的List。 我如何跟踪父母/孩子/叶子?如果父母“父母1”,有两个孩子“孩子A”和“孩子B”,我如何将他们联系在一起?