前言
在使用了FXML設計布局后,新的問題隨之而來,當一個程序需要多個界面時,我們不可能在一個FXML中寫出全部布局,這樣太過於臃腫不易查看和維護(當然非要這么做也是可以的),這里就涉及到如何在一個FXML中添加另一個FXML以及多個FXML對應Controller類之間的通訊。經過查閱發現方法還不止一個,這里分別例舉一下吧。
本文目錄
方式1
這個方法也是我一開始使用的,原理上就是利用`FXMLLoader`加載FXML然后通過代碼添加,假設現有JavaFx項目結構如下: ``` project │ └───java │ │ │ └───main.java │ │ │ └───controller │ ├──mainController.java │ ├──partController.java │ └───resources ├── main.FXML ├── part.FXML ``` 首先以正常情況加載`main.FXML`,那么對於part.FXML,可以在`mainController`的`initializable`方法中使用`FXMLLoader`方法從FXML中獲取布局,再以代碼方式添加到main布局中,有如下偽代碼:/**
* mainController.java
* 偽代碼僅用作示例,無法運行
*/
public class mainController implements Initializable {
@FXML
private GridPane root;
private GridPane part;
@Override
public void initialize(URL location, ResourceBundle resources) {
try {
part=new FXMLLoader(getClass().getClassLoader().getResource("resources/part.fxml")).load();
root.add(part);
} catch (IOException e) {
e.printStackTrace();
}
}
}
那么Controller之間的通信,同樣以上方項目結構為例,假定需要在partController中和mainController實現通信,可以利用HashMap
作為Controller容器來實現傳遞。我們有如下代碼:
mian.java
public class main extends Application {
//創建一個Controller容器
public static Map<String, Object> controllers = new HashMap<String, Object>();
@Override
public void start(Stage primaryStage) throws Exception {
Parent root = new FXMLLoader(getClass().getClassLoader().getResource("resources/main.fxml")).load();
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch();
}
}
如此,在partController.java
定義如下屬性:
private mainControl controller= (mainControl) main.controllers.get(mainControl.class.getSimpleName());
那么在partController
中,我們就可以使用controller.xxx
調用partController
中的公有屬性和方法了。
(此例與上例沒有直接關系)
方式2
在使用過程中,我們可以發現,方法1雖然可以實現通信,但是並不好用,這里就要介紹方法2了。同樣的,還是先從FXML中添加FXML說起。查了資料發現通過同樣的以上面項目結構為例,在main.fxml
中添加part.fxml
有如下偽代碼:
mian.fxml
<AnchorPane fx:id="root" fx:controller="java.controller.mainController" prefHeight="400.0" prefWidth="600.0">
<children>
<fx:include fx:id="part" source="TitlesBar.fxml"/>
</children>
</AnchorPane>
這樣就行了,接下來接着看通信,注意這里前后是連着的,不像上一個方法,前后沒有直接關系。
在mainController.java
中,設置如下屬性:
@FXML
private partController partController;
那么在mainController
中,我們就可以使用partController.xxx
調用partController
中的公有屬性和方法了。
(注意,這里屬性名partController
是根據上一步設置的<fx:include>
中設置的fx:id
來的,格式為id+Controller,如id為'text',則此處應為)
@FXML
private partController textController;
格式不對會報錯無法使用的
完事,結論很明確,方式2更好
參考文章:[https://blog.csdn.net/qq_20336817/article/details/80055701)
(本文最后更新於2020.3.14,原創文章,轉載請注明)