为什么 JFXPanel 将重点放在 TextField 上

Why is JFXPanel giving focus to TextField

以下代码生成包含 JFXPanelJPanelJFrame。每个面板都包含一个文本字段。

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 不保持自己的焦点?为什么将它提供给文本字段?它如何选择要关注的组件?防止它把焦点放在文本字段上的正确方法是什么?

原因是 JFXPanelScene 更接近 focusOwnerProperty

创建 Scene 时,它会将焦点赋予存储在此 属性 中的 Node

这是因为TextField是scene-graph中唯一的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 集中在点击上。