JavaFX 8将多个fxml文件加载到边框中

时间:2015-07-24 22:57:50

标签: javafx fxml

给出以下代码:

public class Main扩展Application {

private BorderPane rootLayout;
private VBox toolbarLayout;

private URL path;

public static void main(String[] args) {
    launch(args);
}

@Override
public void start(Stage stage) {                            

    FXMLLoader loader = new FXMLLoader();                

    // Root View

    path = getClass().getResource("mainLayout.fxml");
    try {
        loader.setLocation(path);            
        rootLayout = (BorderPane) loader.load();
    } catch (IOException e){
        System.out.println("Not found: " + path);
        e.printStackTrace();
    }        

    // Toolbar View
    path = getClass().getResource("toolbar/toolbarView.fxml");  
    try {                        
        toolbarLayout = (VBox) loader.load();
    } catch (IOException e){
        System.out.println("Not found: " + path);
        e.printStackTrace();
    }

    rootLayout.getChildren().add(toolbarLayout);

    Scene scene = new Scene(rootLayout);        
    stage.setScene(scene);
    stage.show();
}

如果我注释掉第二个fxml'试试' rootLayout加载正常。如果我注释掉borderpane并将toolbarView设置为主视图,它也可以正常工作。 但是如果我尝试将toolbarView加载到rootLayout中,则rootLayout加载正常,但toolbarView会抛出异常:

javafx.fxml.LoadException: Root value already specified.

显然我不太了解fxml加载过程,所以有人可以对此有所了解吗?为什么我认为我想再次设置root?

为了完整性,这里是toolbarView.fxml:

<VBox fx:id="idToolbar" alignment="TOP_CENTER" maxHeight="-Infinity"
 maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity"
  prefHeight="400.0" prefWidth="100.0" spacing="20.0" 
xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">

<children>
  <Button mnemonicParsing="false" text="Button" />
  <Button mnemonicParsing="false" text="Button" />
  <Button mnemonicParsing="false" text="Button" />
</children>
  <opaqueInsets>
    <Insets />
  </opaqueInsets>
<padding>
  <Insets top="20.0" />
</padding>
</VBox>

1 个答案:

答案 0 :(得分:3)

root属性包含对FXML文件指定的结构的引用;即到由FXML文件的根元素创建的对象。假设您没有使用"dynamic root" (<fx:root>) pattern,根将被设置为对应于FXML根元素的对象的load进程的一部分。如果在此阶段不是null(即如果已经设置),那么您将获得例外。类似的事情对于controller属性也是如此:如果FXML文件指定fx:controller属性,则控制器将被设置为load()进程的一部分;如果它不是null,则抛出异常。

FXMLLoader实际上只设计为使用一次,因为您有许多相互依赖的属性,这些属性通常设置为加载过程的一部分:rootlocation,{{1 } {},controllerresources的元素。因此,您应该为要加载的每个FXML文件创建一个新的namespace

FXMLLoader

可以通过小心地取消设置作为先前加载过程一部分的任何内容来重用FXMLLoader loader = new FXMLLoader(); // Root View path = getClass().getResource("mainLayout.fxml"); try { loader.setLocation(path); rootLayout = (BorderPane) loader.load(); } catch (IOException e){ System.out.println("Not found: " + path); e.printStackTrace(); } // Toolbar View loader = new FXMLLoader(); path = getClass().getResource("toolbar/toolbarView.fxml"); try { // note you omitted this line: loader.setLocation(path); toolbarLayout = (VBox) loader.load(); } catch (IOException e){ System.out.println("Not found: " + path); e.printStackTrace(); } rootLayout.getChildren().add(toolbarLayout);

FXMLLoader

但这实际上并非预期用途,并且可能对FXMLLoader loader = new FXMLLoader(); // Root View path = getClass().getResource("mainLayout.fxml"); try { loader.setLocation(path); rootLayout = (BorderPane) loader.load(); } catch (IOException e){ System.out.println("Not found: " + path); e.printStackTrace(); } loader.setRoot(null); loader.setController(null); loader.setResources(null); loader.getNamespace().clear(); // Toolbar View path = getClass().getResource("toolbar/toolbarView.fxml"); try { // note you omitted this line: loader.setLocation(path); toolbarLayout = (VBox) loader.load(); } catch (IOException e){ System.out.println("Not found: " + path); e.printStackTrace(); } rootLayout.getChildren().add(toolbarLayout); 实施的未来更改不够健壮。