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

Fre*_*ind 23 nested 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>
Run Code Online (Sandbox Code Playgroud)

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"/>
Run Code Online (Sandbox Code Playgroud)

editor.fxmlfx: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"/>
Run Code Online (Sandbox Code Playgroud)

实际上,我找不到这两种代码的任何区别.我想念什么吗?

Jam*_*s_D 54

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

作为一个例子,想象一下你想要定义一个简单的自定义组件,由a组成TextFieldButton包含在HBox.你需要用子类来表示它Node,所以你可以编写类似的代码

VBox vbox = new VBox();
vbox.getChildren().add(new MyComponent());
Run Code Online (Sandbox Code Playgroud)

问题是你需要一个Java类,它是NodeFXML 的子类.在纯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);
    }
}
Run Code Online (Sandbox Code Playgroud)

使用FXML定义没有<fx:root>元素的自定义组件会产生问题,因为您需要FXML作为某种节点,然后另一个节点实例来表示包装它的类:

<HBox>
<TextField fx:id="textField"/>
<Button fx:id="button" />
</HBox>
Run Code Online (Sandbox Code Playgroud)

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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这导致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>
Run Code Online (Sandbox Code Playgroud)

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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在MyComponent具有与原始全Java版本相同的结构,HBox包含a TextField和a Button.如果没有<fx:root>元素,你不能使用FXML .

  • 而且重要的是,您可以在其他FXML文档中使用MyComponent,就像任何其他控件一样.您可以创建这样的整个层次结构. (6认同)