java - 在 javafx 中检测特定 Pane 外的焦点

标签 java javafx

如何检测焦点是否已离开特定 Pane ?因为 Pane (StackPane) 不可聚焦,所以我在执行此操作时遇到了麻烦。例如,我有一个带有 TextFieldStackPane,如果我按几次 Tab,它就会离开焦点 Pane 并转到另一个 Pane 。如果您离开 StackPane 的焦点,我想通过将焦点设置回 Pane 中的第一个 TextField 来防止这种行为。

这是我的尝试:

myStackPane().focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
            if (! isNowFocused) {
                setFocus(node);
            }
        });

但我认为这不起作用,因为 StackPane 不可聚焦。我也尝试过这样的 isFocused() 方法:

myStackPane.focusedProperty().addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
            if(pane.isFocused()){
                System.out.println("not focused");
                setFocus(node);
            }else{
                System.out.println("is focused");
            }
        });

但是,正如预期的那样,它没有产生想要的结果。

最佳答案

正如您所发现的,当 child 获得焦点时,父项的 focused 属性未设置为 true,因此检查父项是否获得焦点对您没有帮助.您必须测试新获得焦点的 Node 是否是您希望保持焦点的父节点的后代;如果不是,请将重点放在适当的 child 身上。这是一个基本示例:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class App extends Application {

    private static boolean isParentAncestorOfNode(Parent parent, Node node) {
        if (parent == null || node == null || parent == node || node.getParent() == null) {
            return false;
        }

        Parent current = node.getParent();
        do {
            if (current.equals(parent)) {
                return true;
            }
            current = current.getParent();
        } while (current != null);
        return false;
    }

    @Override
    public void start(Stage primaryStage) {
        VBox innerBox = new VBox(15);
        for (int i = 1; i <= 3; i++) {
            innerBox.getChildren().add(new TextField("Field #" + i));
        }

        VBox root = new VBox(15, innerBox, new TextField("Field #4"));
        root.setPadding(new Insets(25));
        root.setAlignment(Pos.CENTER);
        VBox.setVgrow(innerBox, Priority.ALWAYS);

        Scene scene = new Scene(root);
        scene.focusOwnerProperty().addListener((observable, oldNode, newNode) -> {
            if (!isParentAncestorOfNode(innerBox, newNode)) {
                innerBox.getChildren().get(0).requestFocus();
            }
        });

        primaryStage.setScene(scene);
        primaryStage.show();
    }

}

一旦焦点尝试转到第四个 TextField,它将转而关注第一个 TextField这是绝对的。换句话说,无论如何(例如 Tab、用鼠标单击、以编程方式请求焦点)第四个 TextField 将无法获得焦点 — 任何不是后代的东西也不会的 innerBox。我不确定这是否是所需的行为。要禁用该行为,只需从 focusOwner 属性中删除 ChangeListener(将要求您保留对监听器的引用)。当然,您可以尝试修改代码,使其更加细微。

关于java - 在 javafx 中检测特定 Pane 外的焦点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58100040/

相关文章:

javafx - 我从 FXML 文件调用样式表 (css) 的语法有什么问题?

JavaFX 切换按钮阴影

java - 如何从 JavaFX 中的 AnchorPane 获取组件

java - 如何在 jooq 中管理 DSLContext? (关闭连接)

java - 如何从另一个 JInternalFrame 调用 JInternalFrame?

java - 希望学习OOP语言的AS400程序员。 Java或.Net哪个更好

Java FX TranslateTransition 持续时间更改

java - 将 Android 布局与 LayoutBaseGameActivity 一起使用时,Andengine 上出现奇怪的问题?

Java - 制作三角形类

java - SwingFXUtils 图像序列化替代方案(Javafx、Swing、Raspberry Pi)