如何确定用户是否在特定JavaFX节点之外单击?

Vol*_*ort 1 java javafx

我有一个TextField,如果用户单击不是其本身的任何位置,我想做些事情TextField

  • 显然,onMouseClicked如果您不单击节点本身,则事件不会触发,因此将无法正常工作。
  • 侦听focusedProperty可能是一个好主意,但问题是我的应用程序几乎整个都无法遍历焦点,因此在许多情况下,在文本字段之外单击不会使焦点不集中,因此不会通知侦听器。

我唯一想做的就是在事件本身上放置一个事件过滤器,拦截鼠标单击,获取单击坐标并确定它们是否在文本框的范围内。我发现这有点矫kill过正,我可能会缺少一些显而易见的东西。

还有另一种方法来确定用户是否单击了我TextField节点之外的任何地方?

fab*_*ian 5

我唯一想做的就是在事件本身上放置一个事件过滤器,拦截鼠标单击,获取单击坐标并确定它们是否在文本框的范围内。我发现这有点矫kill过正,我可能会缺少一些显而易见的东西。

实际上,我认为这是您最好的选择,但有一些变化:

使用PickResult由提供MouseEvent以获得目标Node和检查,如果它在的层次结构Node。(如果Node具有子元素,则这可能是必要的;例如,a TextField也包含一个Text元素。)

实际上,这似乎是无法通过消耗场景图中某个地方的事件来打破的唯一选择。

如果用户单击以外的其他位置,这会将焦点移到根窗格TextField

public static boolean inHierarchy(Node node, Node potentialHierarchyElement) {
    if (potentialHierarchyElement == null) {
        return true;
    }
    while (node != null) {
        if (node == potentialHierarchyElement) {
            return true;
        }
        node = node.getParent();
    }
    return false;
}

@Override
public void start(Stage primaryStage) {
    TextField textField = new TextField();
    textField.setMinSize(400, Region.USE_PREF_SIZE);
    textField.setMaxWidth(400);
    textField.setEditable(false);
    textField.textProperty().bind(Bindings.when(textField.focusedProperty()).then("Got the Focus!").otherwise("Please give me the focus!"));

    StackPane root = new StackPane();
    root.getChildren().add(textField);

    Scene scene = new Scene(root, 500, 200);

    scene.addEventFilter(MouseEvent.MOUSE_CLICKED, evt -> {
        if (!inHierarchy(evt.getPickResult().getIntersectedNode(), textField)) {
            root.requestFocus();
        }
    });

    primaryStage.setScene(scene);
    primaryStage.show();
}
Run Code Online (Sandbox Code Playgroud)