(My) expected behaviour:
When you call setFocusTraversable(false)
on a Node with children (i.e. the Node has a method getChildren()
that returns a List of Node
s) the focusTraversable
properties of that node and all its children get the value false
.
Actual behaviour:
However, when I call setFocusTraversable(false)
on for example a TextFlow
, its children are still being able to receive focus. This is illustrated in the code below.
Why does the setFocusTraversable(boolean)
method work this way, and how should one work around this limitation?
// File: App.java
package nl.aronhoogeveen.bugreports;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Hyperlink;
import javafx.scene.layout.BorderPane;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.stage.Stage;
/**
* JavaFX App
*/
public class App extends Application {
@Override
public void start(Stage stage) {
// TextFlow 1
Text text1 = new Text("This is text1");
Hyperlink hyperlink1 = new Hyperlink("This is hyperlink1");
Text text2 = new Text("This is text2");
Hyperlink hyperlink2 = new Hyperlink("This is hyperlink2");
TextFlow textFlow1 = new TextFlow(text1, hyperlink1, text2, hyperlink2);
textFlow1.setFocusTraversable(false);
// TextFlow 2 (CustomTextFlow)
Text text3 = new Text("This is text3");
Hyperlink hyperlink3 = new Hyperlink("This is hyperlink3");
Text text4 = new Text("This is text4");
Hyperlink hyperlink4 = new Hyperlink("This is SPARTAAAAA");
CustomTextFlow textFlow2 = new CustomTextFlow(text3, hyperlink3, text4, hyperlink4);
textFlow2.customSetFocusTraversable(false);
BorderPane rootBorderPane = new BorderPane();
rootBorderPane.setTop(textFlow1);
rootBorderPane.setBottom(textFlow2);
stage.setScene(new Scene(rootBorderPane));
stage.sizeToScene();
stage.show();
}
public static void main(String[] args) {
launch();
}
}
// File: CustomTextFlow.java
package nl.aronhoogeveen.bugreports;
import javafx.scene.Node;
import javafx.scene.text.TextFlow;
public class CustomTextFlow extends TextFlow {
public CustomTextFlow(Node... children) {
super(children);
}
/**
* Sets the property focusTraversable of all children's children to {@code b}.
*
* @param b the value to set for the properties
*/
public void customSetFocusTraversable(boolean b) {
for (Node child : getChildren()) {
// Assume for simplicity that the children are not Parents or other types that have children
child.setFocusTraversable(b);
}
}
}
I filed a bug on the ControlsFX component HyperlinkLabel
regarding this behaviour, and after investigating I discovered that this behaviour was already present in the JavaFX TextFlow
component that is used by the HyperlinkLabel and therefore I am posting this question.