是否可以在不重新读取的情况下多次添加从 FXML 文件加载的组件?
Is it possible to add a component loaded from an FXML file more than once without rereading it?
所以我开始使用 javafx,我想知道以下问题:
假设我有一个应用程序,里面有一些容器。
例如:
VBox vBox = new VBox();
我还有一个 FXML 文件,其中包含一些我想多次添加到 vBox
的其他组件。
现在我可以做类似的事情:
for(int i = 0; i < 8; i++) {
vBox.getChildren().add(FXMLLoader.load(getClass().getResource("/someComponent.fxml")));
}
但这对我来说似乎效率很低,因为每次我添加组件时,它都会从文件中重新读取。
有什么方法可以构造一个只读取文件一次的 FXMLLoader,以某种方式保存它,并让我生成文件中定义的组件的新实例?
没有执行此操作的内置方法。 Tom Schindl 正在从事 convert FXML to java source 的项目并在构建时编译源代码。我不知道那个项目目前的状态是什么(我提供的link有下载,但是他说功能不完整)
对于桌面应用程序,这不太可能成为问题;在最坏的情况下(在绝大多数用例中),它只会在启动时或响应用户输入时完成(在后一种情况下并不常见)。所以这可能不是问题。
话虽如此,这是一个缓慢的过程。性能有两个明显的问题:一个是读取文件(或其他资源);另一个是读取文件(或其他资源)。第二个是解析 fxml(使用大量反射)。
如果执行此操作确实遇到性能问题,您可以将重复加载的组件从 fxml 移动到 Java。
如果访问资源是瓶颈(我真的不会这样做,除非你有强有力的证据证明这是一个问题;我认为这不太可能是性能问题的原因,除非你从一个远程位置),并且您想将其保存在 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));
}
所以我开始使用 javafx,我想知道以下问题:
假设我有一个应用程序,里面有一些容器。
例如:
VBox vBox = new VBox();
我还有一个 FXML 文件,其中包含一些我想多次添加到 vBox
的其他组件。
现在我可以做类似的事情:
for(int i = 0; i < 8; i++) {
vBox.getChildren().add(FXMLLoader.load(getClass().getResource("/someComponent.fxml")));
}
但这对我来说似乎效率很低,因为每次我添加组件时,它都会从文件中重新读取。
有什么方法可以构造一个只读取文件一次的 FXMLLoader,以某种方式保存它,并让我生成文件中定义的组件的新实例?
没有执行此操作的内置方法。 Tom Schindl 正在从事 convert FXML to java source 的项目并在构建时编译源代码。我不知道那个项目目前的状态是什么(我提供的link有下载,但是他说功能不完整)
对于桌面应用程序,这不太可能成为问题;在最坏的情况下(在绝大多数用例中),它只会在启动时或响应用户输入时完成(在后一种情况下并不常见)。所以这可能不是问题。
话虽如此,这是一个缓慢的过程。性能有两个明显的问题:一个是读取文件(或其他资源);另一个是读取文件(或其他资源)。第二个是解析 fxml(使用大量反射)。
如果执行此操作确实遇到性能问题,您可以将重复加载的组件从 fxml 移动到 Java。
如果访问资源是瓶颈(我真的不会这样做,除非你有强有力的证据证明这是一个问题;我认为这不太可能是性能问题的原因,除非你从一个远程位置),并且您想将其保存在 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));
}