JavaFX 8将多个fxml文件加载到borderpane中 [英] JavaFX 8 loading multiple fxml files into borderpane

查看:302
本文介绍了JavaFX 8将多个fxml文件加载到borderpane中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出以下代码:

公共类Main扩展Application {

public class Main extends 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'try',则rootLayout可以正常加载.如果我注释掉边框,并将toolbarView设置为主视图,它也可以正常工作. 但是,如果我尝试将toolbarView加载到rootLayout中,则rootLayout可以很好地加载,但是toolbarView会引发异常:

If I comment out the second fxml 'try' the rootLayout loads fine. If I comment out the borderpane and set the toolbarView as the main view it works fine too. BUT if I try to load the toolbarView into the rootLayout, the rootLayout loads fine, but the toolbarView throws an exception:

javafx.fxml.LoadException: Root value already specified.

很显然,我对fxml的加载过程不太了解,所以有人可以对此进行一些说明吗?为什么认为我要重新设置根目录?

Obviously I don't understand the fxml load process well enough, so can someone please throw some light on this? Why does it think I am trying to set the root again?

为完整起见,这是工具栏View.fxml:

For completeness, here is the 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>

推荐答案

root属性包含对FXML文件指定的结构的引用.即由FXML文件的根元素创建的对象.假设您没有使用动态根"(<fx:root>)模式,则根将作为load进程的一部分设置为与FXML根元素相对应的对象.如果在此阶段它不是null(即如果它已经被设置),那么您将得到一个异常.对于controller属性,情况也是如此:如果FXML文件指定了fx:controller属性,则将控制器设置为load()进程的一部分;如果不是null,则会引发异常.

The root property contains a reference to the structure specified by the FXML file; i.e. to the object created by the root element of the FXML file. Assuming you are not using the "dynamic root" (<fx:root>) pattern, the root will be set as part of the load process to the object corresponding to the root element of the FXML. If it is not null at this stage (i.e. if it has already been set), then you will get an exception. A similar thing is true for the controller property: if the FXML file specifies an fx:controller attribute, the controller will be set as part of the load() process; if it is not null, an exception is thrown.

FXMLLoader实际上仅设计为只能使用一次,因为您具有许多相互依赖的属性,这些属性通常在加载过程中进行设置:rootlocationcontrollerresourcesnamespace的元素.因此,您实际上应该为要加载的每个FXML文件创建一个新的FXMLLoader:

The FXMLLoader is really only designed to be used once, as you have many interdependent properties which are typically set as part of the load process: root, location, controller, resources, and elements of the namespace. So you should really create a new FXMLLoader for each FXML file you want to load:

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:

It may be possible to reuse an FXMLLoader by carefully unsetting anything that has been set as part of the previous load process:

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

,但这实际上不是预期的用法,并且可能对将来对FXMLLoader实现的更改不可靠.

but this is really not the intended usage, and may not be robust to future changes to the FXMLLoader implementation.

这篇关于JavaFX 8将多个fxml文件加载到borderpane中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆