JavaFX之多個FXML載入和通訊

  • 2020 年 3 月 14 日
  • 筆記

前言

在使用了FXML設計布局後,新的問題隨之而來,當一個程式需要多個介面時,我們不可能在一個FXML中寫出全部布局,這樣太過於臃腫不易查看和維護(當然非要這麼做也是可以的),這裡就涉及到如何在一個FXML中添加另一個FXML以及多個FXML對應Controller類之間的通訊。經過查閱發現方法還不止一個,這裡分別例舉一下吧。

本文目錄

1. 方式1

2. 方式2(推薦)


方式1

這個方法也是我一開始使用的,原理上就是利用FXMLLoader載入FXML然後通過程式碼添加,假設現有JavaFx項目結構如下:

project  │  └───java  │   │  │   └───main.java  │   │  │   └───controller  │       ├──mainController.java  │       ├──partController.java  │  └───resources      ├── main.FXML      ├──  part.FXML

首先以正常情況載入main.FXML,那麼對於part.FXML,可以在mainControllerinitializable方法中使用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 controller;

那麼在mainController中,我們就可以使用controller.xxx調用partController中的公有屬性和方法了。


完事,結論很明確,方式2更好


參考文章:[https://blog.csdn.net/qq_20336817/article/details/80055701)

(本文最後更新於2020.3.14,原創文章,轉載請註明)