UtterlyConfused
UtterlyConfused

Reputation: 1083

Why is JFXPanel giving focus to TextField

The following code produces a JFrame containing a JFXPanel and a JPanel. Each of the panels contains a text field.

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));

Suppose we start with the Swing text field focused. Then suppose I click inside the JFXPanel (but not within the bounds of its text field). The JFXPanel gives focus to the TextField.

Why does this happen? Why does the JFXPanel not keep its own focus? Why does it give it to the text field? How does it choose which of its components to give focus to? What is the correct way to prevent it giving its focus to the text field?

Upvotes: 1

Views: 251

Answers (1)

DVarga
DVarga

Reputation: 21799

The reason is the Scene of the JFXPanel and more closely its focusOwnerProperty.

When the Scene is created, it gives the focus to the Node stored in this property.

This is because of the TextField is the only Node in the scene-graph, which is 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().

As a solution you can add the following

Platform.runLater(() -> {
    root.setOnMouseClicked(e -> root.requestFocus());
});

This will focus the FlowPane on click.

Upvotes: 1

Related Questions