Java 文本字段中的RequestFocus不';行不通
我使用JavaFX2.1,并使用FXML创建GUI,在这个GUI的控制器中添加了Java 文本字段中的RequestFocus不';行不通,java,javafx-2,fxml,Java,Javafx 2,Fxml,我使用JavaFX2.1,并使用FXML创建GUI,在这个GUI的控制器中添加了myTextField.requestFocus() 但是我总是在另一个控件中获得焦点。在initialize()时,控件尚未准备好处理焦点 您可以尝试下一个技巧: @Override public void initialize(URL url, ResourceBundle rb) { Platform.runLater(new Runnable() { @Override
myTextField.requestFocus()代码>
但是我总是在另一个控件中获得焦点。在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版本中发生了更改或中断,那么最好为重复添加一个限制,以避免无休止的循环。失去焦点比整个应用程序更好。:)
具有所述阈值的示例:
@覆盖
public void requestFocus(){
requestFocus(getNode(),3);
}
私有void requestFocus(最终节点,最终int max){
如果(最大值>0){
朗莱特(
() -> {
如果(!node.isFocused()){
requestFocus();
请求焦点(节点,最大值-1);
}
}
);
}
}
如果您请求Focus()初始化场景后,它将工作
像这样:
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();
我希望这有帮助。:) 答案与@Sergey Grinev完全相同。确保您的java版本是最新的(JDK1.8或更高版本)
当尚未设置节点的场景属性时,可能会发生这种情况。
唉,设置场景属性可能需要“很长”的时间
第一次创建场景时,以及将项目添加到某些父节点(例如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()
}
}
也许有人想把它翻译成Java。我在使用JavaFX11时遇到了同样的问题,并用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);
ChangeListener sceneListener=new ChangeListener(){
@凌驾
public void changed(observevalue较旧的答案解释了Platform.runLater
不工作的情况,但此答案也涵盖了多个节点上的多个请求的情况
问题是:scene
属性对于节点变为非null的顺序,以及由此调用添加的侦听器的顺序,不一定与添加两个侦听器的顺序相同。因此,此顺序:
requestFocusOnSceneAvailable(node1)
requestFocusOnSceneAvailable(node2)
node2.requestFocus()
node1.requestFocus()
可能意外地导致以下顺序:
requestFocusOnSceneAvailable(node1)
requestFocusOnSceneAvailable(node2)
node2.requestFocus()
node1.requestFocus()
解决方案要求侦听器仅在最近的节点上调用requestFocus()
,可以使用静态变量跟踪该节点:
private static Node nodeToRequestFocusOnOnceSceneAvailable;
public static void requestFocusOnceSceneAvailable(Node node) {
// Remember this node as the latest node requested to receive focus.
nodeToRequestFocusOnOnceSceneAvailable = node;
// Schedule the focus request to happen whenever
// JavaFX finally adds the node to the scene.
Listeners.addAndFire(node.sceneProperty(), new ChangeListener<Scene>() {
@Override
public void changed(ObservableValue<? extends Scene> observable, Scene oldScene, Scene newScene) {
if (newScene != null) {
if (node == nodeToRequestFocusOnOnceSceneAvailable) {
node.requestFocus();
// We no longer need to remember this node,
// since its focus has been requested.
nodeToRequestFocusOnOnceSceneAvailable = null;
}
// We no longer need the listener
// after it has run once.
observable.removeListener(this);
}
}
});
}
私有静态节点NodeToRequestFocusOnceSceneAvailable;
公共静态void requestFocusOnceSceneAvailable(节点){
//记住此节点是请求接收焦点的最新节点。
NodeToRequestFocusOnceSceneAvailable=节点;
//安排焦点请求在任何时候发生
//JavaFX最终将节点添加到场景中。
addAndFire(node.sceneProperty(),new ChangeListener()){
@凌驾
更改公众假期(Observalevalue)我有一个相关的问题,我的TextArea
拒绝以编程方式获取焦点,即使该阶段可见且处于活动状态,并且当前正在运行的线程是JavaFX应用程序线程。但是如果我按照示例将一个新的Runnable
排队,它就工作了。真奇怪,我对此没有任何解释。Th似乎不再适用于JavaFX 8。tf==null
在initialize
运行时仍然为真。@skiwi,这意味着FXML中存在错误:检查@FXML注释,“fx:id”标记以及两者中变量的拼写。所有@FXML ed控件在initialize()处都不应为null
time。否则,initialize()有什么意义
方法?此解决方案在10%的情况下有效,90%的情况下无效。我是说相同的代码,相同的程序。是否有其他方法可以检测文本字段何时准备好请求焦点?@Pavel_K 100%适用于我。如果您有特定的情况,最好在单独的问题中显示。另一个选项可以是codepleb的答案——它应该在没有任何计时技巧的情况下工作。