在javafx中检测特定窗格外的焦点
如何检测焦点已离开特定窗格?由于窗格(在javafx中检测特定窗格外的焦点,java,javafx,Java,Javafx,如何检测焦点已离开特定窗格?由于窗格(StackPane)不可聚焦,因此我在执行此操作时遇到问题。例如,我有一个带有TextFields的StackPane,如果我多次按tab键,它将离开焦点窗格并转到另一个窗格。如果您离开StackPane的焦点,我想通过将焦点设置回窗格中的第一个TextField来防止这种行为 这是我的尝试: myStackPane().focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
StackPane
)不可聚焦,因此我在执行此操作时遇到问题。例如,我有一个带有TextField
s的StackPane
,如果我多次按tab键,它将离开焦点窗格并转到另一个窗格。如果您离开StackPane
的焦点,我想通过将焦点设置回窗格中的第一个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");
}
});
myStackPane.focusedProperty().addListener((ObservalEvalue正如您所发现的,当一个子节点被聚焦时,父节点的聚焦
属性没有设置为true
,因此检查父节点是否聚焦对您没有帮助。您必须测试新聚焦的节点
是否是您希望保持聚焦的父节点的后代;如果不是,则请求聚焦他是个合适的孩子。下面是一个初步的例子:
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();
}
}
导入javafx.application.application;
导入javafx.geometry.Insets;
导入javafx.geometry.Pos;
导入javafx.scene.Node;
导入javafx.scene.Parent;
导入javafx.scene.scene;
导入javafx.scene.control.TextField;
导入javafx.scene.layout.Priority;
导入javafx.scene.layout.VBox;
导入javafx.stage.stage;
公共类应用程序扩展应用程序{
私有静态布尔isParentAncestorOfNode(父-父,节点-节点){
if(parent==null | | node==null | | parent==node | | node.getParent()==null){
返回false;
}
当前父节点=node.getParent();
做{
if(当前等于(父级)){
返回true;
}
current=current.getParent();
}while(当前!=null);
返回false;
}
@凌驾
公共无效开始(阶段primaryStage){
VBox innerBox=新的VBox(15);
对于(int i=1;i{
if(!isParentAncestorOfNode(innerBox,newNode)){
innerBox.getChildren().get(0.requestFocus();
}
});
初级阶段。场景(场景);
primaryStage.show();
}
}
一旦焦点尝试转到第四个文本字段
,它将聚焦第一个文本字段
,这是绝对的。换句话说,无论发生什么情况(例如,选项卡,用鼠标单击,以编程方式请求焦点)第四个TextField
将无法聚焦,也不会有任何东西不是innerBox
的后代。我不确定这是否是所需的行为。要禁用该行为,只需从focusOwner
属性中删除ChangeListener
(需要保留对侦听器的引用)。当然,您可以尝试修改代码,使其更加细致