Подтвердить что ты не робот

Как понять и использовать `<fx: root>`, в JavaFX?

Он говорит, что тег fx:root был добавлен в javafx 2.2, но я не понимаю, как его использовать, хотя с этим примером: http://docs.oracle.com/javafx/2/fxml_get_started/whats_new2.htm

main.xml

<?import javafx.scene.layout.GridPane?>
<GridPane fx:controller="sample.Controller"
          xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
    <fx:include fx:id="editorPane" source="editor.fxml"/>
</GridPane>

editor.fxml без fx:root:

<?import javafx.scene.control.TextArea?>
<TextArea fx:id="editor" prefWidth="500" prefHeight="400" 
   fx:controller="sample.EditorController"
   xmlns:fx="http://javafx.com/fxml"/>

editor.fxml с fx:root:

<fx:root type="javafx.scene.control.TextArea"
     fx:id="editor" prefWidth="500" prefHeight="400"
     fx:controller="sample.EditorController"
     xmlns:fx="http://javafx.com/fxml"/>

На самом деле, я не могу найти разницы для двух видов кода. Мне что-то не хватает?

4b9b3361

Ответ 1

<fx:root> обеспечивает решение проблемы определения повторно используемого компонента с помощью FXML.

В качестве примера представьте, что вы хотите определить простой пользовательский компонент, состоящий из TextField и Button, содержащихся в HBox. Вам нужно, чтобы это было представлено подклассом Node, поэтому вы можете написать код типа

VBox vbox = new VBox();
vbox.getChildren().add(new MyComponent());

Проблема в том, что вам нужен класс Java, который является подклассом Node, а также FXML. В чистой Java (без FXML) вы можете сделать это с помощью

public class MyComponent extends HBox {
    private TextField textField ;
    private Button button ;

    public MyComponent() {
        textField = new TextField();
        button = new Button();
        this.getChildren().addAll(textField, button);
    }
}

Использование FXML для определения настраиваемого компонента без элемента <fx:root> представляет проблему, потому что вам нужен FXML как какой-то node, а затем еще один экземпляр node для представления класса, обертывающего его:

<HBox>
<TextField fx:id="textField"/>
<Button fx:id="button" />
</HBox>

и

public class MyComponent extends HBox {
    @FXML
    private TextField textField ;
    @FXML
    private Button button ;
    public MyComponent() {
        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("MyComponent.fxml"));
            loader.setController(this);
            HBox hbox = loader.load();
            this.getChildren().add(hbox);
        } catch (IOException exc) {
            // handle exception
        }
    }
}

В результате MyComponent состоит из HBox, обертывающего HBox, обертывающий TextField и Button. Дополнительный избыточный HBox является результатом необходимости использования одного node для корня FXML и одного node для представления компонента.

<fx:root> дает механизм создания node в качестве компонента (класс Java), а затем инструктирует файл FXML использовать этот node как его корень:

<fx:root type="javafx.scene.layout.HBox">
<TextField fx:id="textField" />
<Button fx:id="button" />
</fx:root>

и

public class MyComponent extends HBox {
    @FXML 
    private TextField textField ;
    @FXML
    private Button button ;
    public MyComponent() {
        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("MyComponent.fxml"));
            loader.setController(this);
            loader.setRoot(this);
            loader.load();
        } catch (IOException exc) {
            // handle exception
        }
    }
}

Теперь MyComponent имеет ту же структуру, что и исходная версия all-Java, a HBox, содержащая TextField и a Button. Вы не можете сделать это с помощью FXML без элемента <fx:root>.