如何在JavaFX中理解和使用`<fx:root>`?</fx:root>

时间:2014-05-12 04:12:17

标签: javafx nested

它表示标记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"/>

实际上,我发现这两种代码没有任何区别。我错过了什么吗?

1 个答案:

答案 0 :(得分:53)

<fx:root>提供了使用FXML定义可重用组件的问题的解决方案。

例如,假设您要定义一个由TextField中包含的ButtonHBox组成的简单自定义组件。您需要使用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作为某种节点,然后另一个节点实例来表示包装它的类:

<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包裹一个包裹TextField和Button的HBox组成。额外的冗余HBox是因为需要一个节点用于FXML根节点而一个节点代表该组件。

<fx:root>提供了一种机制来创建Node作为组件(Java类),然后指示FXML文件将该节点用作其根:

<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具有与原始全Java版本相同的结构,HBox包含TextFieldButton。如果没有<fx:root>元素,则无法使用FXML执行此操作。