JavaFXのFXMLでfx:includeを使ったときの罠

JavaFX + Kotlinでアプリを作っている最中なのですが、ハマったのでメモ。
JavaFXのSceneBuilderでズバッと部品を置いていくとFXMLができてくれるのですが、あまりにも長くなると読みにくいので、パーツ化していこうと思ってメニューをfx:includeで切り出しました。

最初のコードはこんな感じ。見通しをよくするために属性を削ってますので注意。
main.fxml(fx:controllerでcom.example.Controllerを指定)

<?xml version="1.0" encoding="UTF-8"?>
<VBox xmlns:fx="http://javafx.com/fxml"
      fx:controller="com.example.Controller">
  <children>
    <fx:include source="menu_bar.fxml"/>
    <TableView fx:id="table">
      <columns>
        <TableColumn text="No." fx:id="idColumn" />
        <TableColumn text="名前" fx:id="nameColumn" />
        <TableColumn text="E-mail" fx:id="emailColumn" />
      </columns>
    </TableView>
    <!-- 略 -->
  </children>
</VBox>

menu_bar.fxml(同じく、fx:controllerでcom.example.Controllerを指定)

<?xml version="1.0" encoding="UTF-8"?>
<MenuBar
    xmlns:fx="http://javafx.com/fxml"
    fx:controller="com.example.Controller">
    <!-- 略 -->
</MenuBar>

TableViewを使っているので、テーブルを表示しようとController#initializeメソッド内でテーブルを初期化しようとしたところ、ぬるぽで落ちました。
私は単純に、includeはFXMLの中にFXMLを埋め込むだけのものだろうと思っていたのですが、どうやら違うようです。

どうもfxmlファイル毎に初期化処理が行われるようで、2つのfxmlファイルが1つのコントローラーを指定していたらinitializeメソッドが正常に機能しないようです。
ここでは、main.fxmlとmenu_bar.fxmlで別々にControllerを定義する必要があります。

menu_bar.fxml(fx:controllerでcom.example.MenuControllerを指定)

<?xml version="1.0" encoding="UTF-8"?>
<MenuBar
    xmlns:fx="http://javafx.com/fxml"
    fx:controller="com.example.MenuController">
    <!-- 略 -->
</MenuBar>

そして、メニュー用のコントローラーを作ればOK。
1つのコントローラーではダメなんですねぇ…。


カテゴリー Java, Kotlin | タグ   | パーマリンク

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です