Java 是否可以在不重新读取的情况下多次添加从FXML文件加载的组件?

Java 是否可以在不重新读取的情况下多次添加从FXML文件加载的组件?,java,javafx,fxml,Java,Javafx,Fxml,因此,我开始使用javafx,我想知道以下几点: 假设我有一个内置容器的应用程序。 例如: VBox VBox=new VBox() 我还有一个FXML文件,其中包含一些其他组件,我想多次添加到vBox。 现在我可以做一些类似的事情: for(int i = 0; i < 8; i++) { vBox.getChildren().add(FXMLLoader.load(getClass().getResource("/someComponent.fxml"))); } for(i

因此,我开始使用javafx,我想知道以下几点:

假设我有一个内置容器的应用程序。
例如:
VBox VBox=new VBox()
我还有一个FXML文件,其中包含一些其他组件,我想多次添加到
vBox

现在我可以做一些类似的事情:

for(int i = 0; i < 8; i++) {
    vBox.getChildren().add(FXMLLoader.load(getClass().getResource("/someComponent.fxml")));
}
for(int i=0;i<8;i++){
vBox.getChildren().add(fxmloader.load(getClass().getResource(“/someComponent.fxml”));
}
但这对我来说效率很低,因为每次我添加组件时,它都会从文件中重新读取。

有没有办法构造一个FXMLLoader,它只读取文件一次,以某种方式保存文件,并让我生成文件中定义的组件的新实例?

没有内置的方法可以做到这一点。Tom Schindl正在进行一个项目,以便在构建时编译源代码。我不知道该项目的当前状态(我提供的链接有下载,但他说功能不完整)

对于桌面应用程序,这不太可能是一个问题;在最坏的情况下(在绝大多数用例中),它只会在启动时或响应用户输入时进行(在后一种情况下并不频繁)。因此,这可能不是一个问题

尽管如此,这是一个缓慢的过程。性能方面有两个截然不同的问题:一个是读取文件(或其他资源);第二个是解析fxml(它使用大量的反射)

如果执行此操作时确实存在性能问题,则可以将重复加载的组件从fxml移动到Java

如果访问资源是瓶颈(我真的不会这样做,除非你有强有力的证据证明这是一个问题;我认为这不太可能是性能问题的原因,除非你从远程位置加载FXML),并且你想把它保存在FXML中,您可以将FXML加载到内存中,并让
FXMLLoader
ByteArrayInputStream
读取:

    URL fxmlResource = getClass().getResource("/SomeComponent.fxml") ;
    InputStream inputStream = fxmlResource.openStream();
    byte[] buffer = new byte[8192];
    int totalBytes = 0 ;
    int bytesRead ;
    while((bytesRead = inputStream.read(buffer, totalBytes, buffer.length - totalBytes)) != -1) {
        totalBytes += bytesRead ;
        if (totalBytes == buffer.length) {
            byte[] newBuffer = new byte[2 * buffer.length];
            System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
            buffer = newBuffer ;
        }
    }

    inputStream.close();
    byte[] content = new byte[totalBytes];
    System.arraycopy(buffer, 0, content, 0, totalBytes);

    InputStream fxml = new ByteArrayInputStream(content);

    VBox vbox = new VBox(5);
    for(int i = 0; i < 8; i++) {
        FXMLLoader loader = new FXMLLoader();
        fxml.reset();
        vBox.getChildren().add(loader.load(fxml));
    }
URL fxmlResource=getClass().getResource(“/SomeComponent.fxml”);
InputStream InputStream=fxmlResource.openStream();
字节[]缓冲区=新字节[8192];
int totalBytes=0;
int字节读取;
而((bytesRead=inputStream.read(buffer,totalBytes,buffer.length-totalBytes))!=-1){
totalBytes+=字节读取;
if(totalBytes==buffer.length){
byte[]newBuffer=新字节[2*buffer.length];
数组复制(缓冲区,0,新缓冲区,0,缓冲区长度);
缓冲区=新缓冲区;
}
}
inputStream.close();
字节[]内容=新字节[totalBytes];
System.arraycopy(缓冲区,0,内容,0,总字节);
InputStream fxml=新的ByteArrayInputStream(内容);
VBox VBox=新的VBox(5);
对于(int i=0;i<8;i++){
FXMLLoader=新的FXMLLoader();
fxml.reset();
vBox.getChildren().add(loader.load(fxml));
}

中提到了一个“模板标志”,在这里可能会有所帮助。不幸的是,除了文档之外,它似乎在API中的任何地方都不存在,所以我猜这是一个实验性的特性,它要么从未完全实现,要么部分实现,然后从公共API中删除。从我以前的FXML加载程序基准测试中,最大的性能损失是它使用了反射而不是读取文件(当然,对于您的情况,最好两种操作都只执行一次)。关于FXML模板的一些简要讨论。另请参见。我在JavaFXBug跟踪器中创建了一个问题,以修复
FXMLLoader
javadoc。