如何检测焦点是否已离开特定 Pane ?因为 Pane (StackPane
) 不可聚焦,所以我在执行此操作时遇到了麻烦。例如,我有一个带有 TextField
的 StackPane
,如果我按几次 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/