2015-02-23 66 views
3

所以我開始與javafx,我想知道以下內容:是否可以在不重新讀取的情況下多次添加從FXML文件加載的組件?

可以說我有一個容器內的應用程序。
例如:
VBox vBox = new VBox();
而且我也有一個包含一些其他的成分我要添加到vBox多次的FXML文件。
現在我可以這樣做:

for(int i = 0; i < 8; i++) { 
    vBox.getChildren().add(FXMLLoader.load(getClass().getResource("/someComponent.fxml"))); 
} 

但這似乎非常低效的我,因爲我每次添加組件時,它就會從文件中讀取信息。
有沒有什麼方法可以構建一個只讀取一次文件的FXMLLoader,以某種方式保存它,並讓我生成組件的新實例,如文件中定義的那樣?

+0

的[FXMLLoader文檔(http://docs.oracle。 com/javase/8/javafx/api/javafx/fxml/FXMLLoader.html#load--)提到了一個「模板標誌」,這可能對此有幫助。不幸的是,除了在文檔中,它似乎並不存在於API中的任何地方 - 所以我猜測它是一個實驗性功能,它從未完全實現或部分實現,然後從公共API中刪除。 – jewelsea 2015-02-23 18:50:27

+0

從我以前的FXML加載器的基準測試中,最大的性能影響是它使用反射而不是讀取文件(當然,對於您的情況,最好只能兩次都使用)。 – jewelsea 2015-02-23 18:52:08

+0

[Here's](http://mail.openjdk.java.net/pipermail/openjfx-dev/2013-September/010396.html)關於FXML模板的一些簡要討論。另請參閱[此RFE](https://javafx-jira.kenai.com/browse/RT-23413)。 – 2015-02-23 19:27:41

回答

2

有沒有內置的方式來做到這一點。 Tom Schindl正在製作一個convert FXML to java source的項目,並在編譯時編譯源代碼。我不知道該項目的當前狀態(我提供的鏈接有下載,但他說功能不完整)。

對於桌面應用程序,這不太可能是一個問題;在最壞的情況下(絕大多數情況下),它只會在啓動時或響應用戶輸入(在後一種情況下不頻繁)進行。所以這可能不是一個問題。

話雖如此,這是一個緩慢的過程。性能有兩個不同的問題:一個是讀取文件(或其他資源);第二個是解析fxml(它使用了大量的反射)。

如果您在執行此操作時遇到性能問題,則可以將從fxml反覆加載的組件移至Java。

如果訪問資源是瓶頸(除非您有強有力的證據證明這是一個問題,否則我真的不會這麼做;我認爲這不太可能是性能問題的原因,除非您從加載FXML遠程位置),並要保持它在FXML,你可以在FXML加載到內存和讓從ByteArrayInputStream閱讀FXMLLoader

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)); 
    } 
相關問題