如何检测焦点已离开特定窗格?因为窗格 ( StackPane) 不可聚焦,所以我在执行此操作时遇到了麻烦。例如,我有一个StackPanewith TextFields,如果我多次按 Tab,它会离开焦点窗格并转到另一个窗格。我想阻止这种行为通过设置焦点回到第一个TextField,如果你离开的焦点窗格StackPane。
这是我的尝试:
myStackPane().focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
if (! isNowFocused) {
setFocus(node);
}
});
Run Code Online (Sandbox Code Playgroud)
但我认为由于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");
}
});
Run Code Online (Sandbox Code Playgroud)
但是,正如预期的那样,它没有产生想要的结果。
正如您所发现的,当孩子获得焦点时,父母的focused属性未设置为true,因此检查父母是否获得焦点对您没有帮助。您必须测试新焦点Node是否是您希望将焦点保留在其中的父级的后代;如果不是,请要求关注合适的孩子。这是一个基本的例子:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
一旦焦点试图转到第四个TextField,它将改为聚焦第一个TextField。这是绝对的。换句话说,无论如何(例如Tab,用鼠标单击,以编程方式请求焦点)第四个TextField将无法获得焦点——任何不是innerBox. 我不确定这是否是所需的行为。要禁用该行为,只需ChangeListener从focusOwner属性中删除 即可(将要求您保留对侦听器的引用)。当然,您可以尝试修改代码以使其更加细致。
| 归档时间: |
|
| 查看次数: |
528 次 |
| 最近记录: |