簡體   English   中英

如何重用 JavaFX GUI? 我可以動態更改控制器嗎?

[英]How to reuse JavaFX GUI? Can I change controllers dynamically?

我使用 JavaFX Scene Builder/FXML 設計了一個場景,我想創建該場景的許多實例,但每個場景都有不同的行為。 有沒有辦法動態更改場景/FXML 的控制器?

我想要的是設計一個場景並重用它,但每個實例都有不同的行為。


目前我正在加載 FXML 及其控制器,如下所示:

FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(fxmlFile));
Parent root = (Parent) fxmlLoader.load();
Scene scene = new Scene(root);
Controller controller = fxmlLoader.getController();

可以將自定義Controllerfactory與 FXML 加載器一起使用。 setControllerFactory方法需要一個Callback類型,它是一個只有一個可調用函數的接口:工廠使用的call 該函數(由 FXMLLoader 類調用)期望獲得一個Class對象作為輸入參數,並根據類型提供一個實例化的對象。 以上 Java8 lambdas 可用於提供工廠:

FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(fxmlFile));
loader.setControllerFactory((Class<?> controllerType) ->{
    if(controllerType == Controller.class){
        return new Controller();
    }
});
Parent root = (Parent) fxmlLoader.load();

上面代碼中的參數controllerType是 fxml fx:controller屬性提供的類型,由Java Class loader 決定 當調用 Controllerfactory 時,還沒有實例化任何東西,這就是為什么甚至可以在 fxml 中給出抽象類的原因。 為了實現不同的行為,可以使用繼承。

一個例子是:

class Controller{...}
class FirstController extends Controller{...}
class SecondController extends Controller{...}

工廠可以這樣使用:

FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(fxmlFile));
final int[] instantiatedClasses  = {0};
loader.setControllerFactory((Class<?> controllerType) ->{
    if(controllerType == Controller.class){
        if(0 == instantiatedClasses[0]){
            ++instantiatedClasses[0];
            return new FirstController();
        } else return new SecondController();
    }
});
Parent root = (Parent) fxmlLoader.load();

請注意,這種方式也可以向控制器提供不同的參數,因此繼承可能是一種矯枉過正。 例如,primaryStage 可以提供給控制器,例如用於消除對控制器中不同設置器的需要。

class Controller{
    public Controller(int behaviorParam){...}
}
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(fxmlFile));
final int[] instantiatedClasses  = {-1}; /* so it would start at 0 */
loader.setControllerFactory((Class<?> controllerType) ->{
    if(controllerType == Controller.class){
        ++instantiatedClasses[0]; 
        return new Controller(instantiatedClasses[0]);
    }
});
Parent root = (Parent) fxmlLoader.load();

然而,這種方法的挑戰在於區分相同控制器類型的不同 fxml 實例仍然不是很簡單。 計算實例化類的數量是一種有效的方法,但與任何基於標識符的方法相比,它並沒有提供太多控制。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM