setFocusTraversable для узла с дочерними элементами в JavaFX

#javafx #focus #openjfx

#javafx #фокус #openjfx

Вопрос:

(Мое) ожидаемое поведение:

Когда вы вызываете setFocusTraversable(false) узел с дочерними элементами (т. Е. Узел имеет метод getChildren() , который возвращает список Node s) focusTraversable , свойства этого узла и всех его дочерних элементов получают значение false .

Фактическое поведение:

Однако, когда я вызываю setFocusTraversable(false) , например, a TextFlow , его дочерние элементы все еще могут получать фокус. Это показано в приведенном ниже коде.

Почему setFocusTraversable(boolean) метод работает таким образом, и как следует обойти это ограничение?

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

 

Я обнаружил ошибку в компоненте HyperlinkLabel ControlsFX, касающуюся этого поведения, и после расследования я обнаружил, что это поведение уже присутствует в компоненте JavaFX TextFlow , который используется HyperlinkLabel, и поэтому я публикую этот вопрос.

Комментарии:

1. хм.. что заставляет вас думать, что это свойство применяется к полному поддереву родительского дерева?

2. только что проверил документ — ничего, подтверждающего ваши ожидания, что означает, что в общем случае ожидание неверно. При необходимости разработчики элемента управления могут отключить преобразование focustraversal в дочерние элементы, например, используя пользовательскую FocusTraversalPolicy или привязав их свойство к родительскому (как вы в основном и делаете — за исключением отсутствия каких-либо изменений)

3. Очень аккуратно привязать focusTraversableProperty дочерние элементы к родительскому. Я об этом не подумал. Тогда ваш комментарий прекрасно ответил на оба моих вопроса. Спасибо, что подумали. Если вы превратите свой комментарий в ответ, я исключу его