JavaFX使用FXMLLoader加載fxml文件。其原理應該與Java.lang.ClassLoader類似,但有很大不同。ClassLoader加載中間代碼,在運行環境中生成類對象,而FXMLLoader一方面加載xml格式的文本文件,一方面還要加載由該fxml文件指定的Controller。JavaFX應該建立有一種互動機制,把二者粘合在一起。
一般,使用FXMLLoader加載fxml文件的方法可以分為兩類:1、類方法;2、對象方法。
一、類方法
利用類方法比較簡單快捷,代碼如下:
URL url = getClass().getResource("Example1.fxml");
Parent root = FXMLLoader.load(url);
Scene scene = new Scene(root, 300, 200);
stage.setTitle("User Login");
stage.setScene(scene);
stage.show();
FXMLLoader中有如下類方法,可以簡單幾行代碼實現fxml文件的加載:
static <T> T load(java.net.URL location) static <T> T load(java.net.URL location, java.util.ResourceBundle resources) static <T> T load(java.net.URL location, java.util.ResourceBundle resources, BuilderFactory builderFactory) static <T> T load(java.net.URL location, java.util.ResourceBundle resources, BuilderFactory builderFactory, Callback<java.lang.Class<?>, java.lang.Object> controllerFactory) static <T> T load(java.net.URL location, java.util.ResourceBundle resources, BuilderFactory builderFactory, Callback<java.lang.Class<?>,java.lang.Object> controllerFactory, java.nio.charset.Charset charset)
二、對象方法
相比之下,利用對象方法,可以更加靈活的加載fxml文件,但是代碼要復雜一點。如下:
private Initializable replaceSceneContent(String fxml) throws Exception { FXMLLoader loader = new FXMLLoader(); // 創建對象 loader.setBuilderFactory(new JavaFXBuilderFactory()); // 設置BuilderFactory loader.setLocation(Main.class.getResource(fxml)); // 設置路徑基准 try { InputStream in = Main.class.getResourceAsStream(fxml); AnchorPane page = (AnchorPane) loader.load(in); // 對象方法的參數是InputStream,返回值是Object Scene scene = new Scene(page, 800, 600); stage.setScene(scene); stage.sizeToScene(); return (Initializable) loader.getController(); // 可以得到Controller } finally { in.close(); return null; } }
上面代碼中,首先注意這一句:
AnchorPane page = (AnchorPane) loader.load(in);
其中loader是FXMLLoader的一個實例化對象,load方法的參數是InputStream,不再是URL。並且,因為返回值是Object,所以賦值前要轉型。
采用這種方法有一個很實用的好處,即可以得到Controller:
return (Initializable) loader.getController();
如果程序有多個界面,比如登錄窗口、主數據窗口、或者圖表窗口等等,可以由此增加對各個窗口的操控能力。
還有,設置路徑基准也很有用處。
loader.setLocation(Main.class.getResource(fxml)); // 設置路徑基准
在fxml文件中設置css文件,使用的是相對路徑,而setLocation就是設置路徑的基准。使用類方法的時候,默認把所加載的fxml文件的位置作為基准,setLocation卻可以設置不同於當前文件的路徑。
這樣,你可以根據需要,把不同的fxml文件分別放在不同的包中,只要你設置了唯一的路徑基准,所有fxml中指定的css文件就可以使用同樣的相對路徑。
利用這個功能,我們還加載項目外的fxml文件。這里是我寫的一個例子,其中hello1.fxml和hello2.fxml兩個文件可以放在硬盤里的任何地方,都能加載。在hello1.fxml中更是指定了css文件,hello1.fxml不可能和FxmlSelection.fxml處於同一目錄,但是它們卻使用同樣的相對路徑指定css文件。
<stylesheets> <URL value="@main.css" /> </stylesheets>
