以下代码生成一个包含 JFXPanel
和 JPanel
的 JFrame
。每个面板都包含一个文本字段。
JFXPanel fxPanel = new JFXPanel();
JPanel swingPanel = new JPanel(new FlowLayout());
swingPanel.add(new JTextField("Swing"));
JPanel contentPanel = new JPanel(new BorderLayout());
contentPanel.add(fxPanel, BorderLayout.PAGE_START);
contentPanel.add(swingPanel, BorderLayout.CENTER);
JFrame frame = new JFrame("Main Frame");
frame.setContentPane(contentPanel);
FlowPane root = new FlowPane();
root.getChildren().add(new TextField("FX"));
Scene scene = new Scene(root);
Platform.runLater(() -> fxPanel.setScene(scene));
SwingUtilities.invokeLater(() -> frame.setVisible(true));
假设我们从 Swing 文本字段开始。然后假设我在 JFXPanel 内部单击(但不在其文本字段的范围内)。 JFXPanel
将焦点转移到 TextField
。
为什么会发生这种情况?为什么 JFXPanel 不保持自己的焦点?为什么它把它交给文本字段?它如何选择关注哪些组件?防止其将焦点转移到文本字段的正确方法是什么?
最佳答案
原因是 JFXPanel
的 Scene
以及更接近的 focusOwnerProperty .
创建Scene
时,会将焦点赋予存储在此属性中的Node
。
这是因为 TextField
是场景图中唯一的 Node
,即 focus traversable :
Specifies whether this Node should be a part of focus traversal cycle. When this property is true focus can be moved to this Node and from this Node using regular focus traversal keys. On a desktop such keys are usually TAB for moving focus forward and SHIFT+TAB for moving focus backward. When a Scene is created, the system gives focus to a Node whose focusTraversable variable is true and that is eligible to receive the focus, unless the focus had been set explicitly via a call to requestFocus().
作为解决方案,您可以添加以下内容
Platform.runLater(() -> {
root.setOnMouseClicked(e -> root.requestFocus());
});
这将使 FlowPane
在点击时聚焦。
关于java - 为什么 JFXPanel 将焦点放在 TextField 上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38438207/