TextField中的RequestFocus不起作用

时间:2012-10-05 10:42:47

标签: java javafx-2 fxml

我使用JavaFX 2.1并使用FXML创建GUI,在此GUI的控制器中我添加了myTextField.requestFocus();

但我总是把焦点放在另一个控制中。

7 个答案:

答案 0 :(得分:49)

initialize()时,控件还没有准备好处理焦点。

您可以尝试下一招:

@Override
public void initialize(URL url, ResourceBundle rb) {
    Platform.runLater(new Runnable() {
        @Override
        public void run() {
            tf.requestFocus();
        }
    });
}

对于棘手的复杂应用程序(如评论中的Pavel_K),您可能需要多次重复此例程,然后调用方法行:

private void repeatFocus(Node node) {
    Platform.runLater(() -> {
        if (!node.isFocused()) {
            node.requestFocus();
            repeatFocus(node);
        }
    });
}

请注意,这是一种未记录的方法,如果在未来的Java版本中发生更改或破坏,可以明智地添加重复限制以避免无限循环。最好是失去焦点而不是整个应用程序。 :)

答案 1 :(得分:9)

与@Sergey Grinev完全相同的答案。确保您的Java版本是最新的(JDK 1.8或更高版本)。

true

答案 2 :(得分:8)

如果你requestFocus();初始化场景后,它会起作用!

像这样:

Stage stage = new Stage();
GridPane grid = new GridPane();
//... add buttons&stuff to pane

Scene scene = new Scene(grid, 800, 600);

TEXTFIELD.requestFocus();

stage.setScene(scene);
stage.show();

我希望这会有所帮助。 :)

答案 3 :(得分:1)

我使用JavaFX 11遇到了相同的问题,并以类似于nickthecoder提出的方式解决了这个问题。

ChangeListener<Scene> sceneListener = new ChangeListener<Scene>() {
    @Override
    public void changed(ObservableValue<? extends Scene> observable, Scene oldValue, Scene newValue) {
        if (newValue != null) {
            editInput.requestFocus();
            editInput.sceneProperty().removeListener(this);
        }
    }
};
editInput.sceneProperty().addListener(sceneListener);

基本上,只需将侦听器添加到节点的sceneProperty中,并在设置场景后在该侦听器中请求焦点。我还以这样的方式编写了它:侦听器在调用后将被删除。

答案 4 :(得分:1)

我宁愿使用计时器来强制将焦点放在文本字段上。检查文本字段是否具有焦点的过程是在单独的(后台)线程中完成的。而请求焦点的过程是在 GUI 线程中完成的,在 Platform.runLater() 的帮助下。

//I'd rather using timer to enforce focus
Timer checkIfTFIsFocusedTimer = new Timer();
TimerTask checkIfTFIsFocusedTask = new TimerTask() {
    @Override
    public void run() {
        if (!textField.isFocused()) {
            Platform.runLater(() -> {                        
                textField.requestFocus();
            });
        } else {
            checkIfTFIsFocusedTimer.cancel();
        }
    }
};
checkIfTFIsFocusedTimer
        .scheduleAtFixedRate(checkIfTFIsFocusedTask,
        0, 100);

答案 5 :(得分:0)

当尚未设置“节点”的“场景”属性时,可能会发生这种情况。 las,场景属性可能要花很长时间才能设置。

子节点的场景属性在第一次创建场景时以及在将项目添加到某些父项(例如TabPane)时滞后(奇怪的是有些父项似乎不受感染,我不确定为什么)。

正确的策略一直对我有用:

if (myNode.scene) == null {
    // listen for the changes to the node's scene property,
    // and request focus when it is set
} else {
    myNode.requestFocus()
}

我有一个方便的Kotlin扩展功能,可以做到这一点。

fun Node.requestFocusOnSceneAvailable() {
    if (scene == null) {
        val listener = object : ChangeListener<Scene> {
            override fun changed(observable: ObservableValue<out Scene>?, oldValue: Scene?, newValue: Scene?) {
                if (newValue != null) {
                    sceneProperty().removeListener(this)
                    requestFocus()
                }
            }
        }
        sceneProperty().addListener(listener)
    } else {
        requestFocus()
    }
}

然后您可以从代码中调用它,如下所示:

myNode.requestFocusOnSceneAvailable()

也许有人想将其翻译成Java。

答案 6 :(得分:0)

较旧的答案说明了<ion-back-button>不起作用的情况,但是此答案还涵盖了多个节点上的多个请求的情况。

问题是:节点的<ion-toolbar> <ion-buttons slot="start"> <ion-item lines="none" routerLink="/home"> <ion-img src='path-to-your.png'></ion-img> </ion-item> <ion-text>About</ion-text> </ion-buttons> </ion-toolbar> 属性变为非空的顺序以及因此调用添加的侦听器的顺序不一定与两个侦听器的顺序相同添加。这样的顺序:

06/23/2020 07:57:45

可能会意外导致以下顺序:

06-23-2020

一种解决方案要求仅在最近节点上让侦听器调用Platform.runLater,可以使用静态变量对其进行跟踪:

scene

请注意,此解决方案假定只有一个场景。