やってみればなんてことはないんですが。
Controllerから別のControllerの処理を呼びたいのだけどどうすればいいかわからなかった。
自分的な答えは、コントローラー自身を他のコントローラーに渡しておく、ということでした。
ただ、コントローラーが他のコントローラーを持っておくには、ルールがあるようです。
http://stackoverflow.com/questions/14790785/subcontroller-not-being-injected-into-main-controller
ここによると、FXMLで、includeタグのfx:idに付けた値 + Controllerという名前のコントローラーじゃないとクラスが初期化時に保持してくれないです。
ここが重要のようなので、ミスしないようにしましょう。
<?xml version="1.0" encoding="UTF-8"?>
<VBox xmlns:fx="http://javafx.com/fxml"
fx:controller="com.example.Controller">
<children>
<fx:include fx:id="menuBar" 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>
次に、includeするmenu_bar.fxml。
MenuBarControllerのhogeメソッドに紐づいてます。
<?xml version="1.0" encoding="UTF-8"?>
<MenuBar
xmlns:fx="http://javafx.com/fxml"
fx:controller="com.example.MenuBarController">
<menus>
<Menu mnemonicParsing="false" text="ファイル">
<items>
<MenuItem onAction="#hoge" mnemonicParsing="false" text="hoge" />
</items>
</Menu>
</menus>
</MenuBar>
次に、プロパティ(Javaのメンバ変数)にMenuBarControllerを持つControllerのコード。
ただし、コードはKotlinです。
class Controller : Initializable {
// FXMLはJavaのアノテーション@FXMLと同じ意味
FXML private var menuBarController : MenuBarController? = null
val hoge = "hoge"
public override fun initialize(p0: URL?, p1: ResourceBundle?) {
// 初期化の際に自身を渡しておく
menuBarController!!.controller = this
}
}
最後に、MenuBarController。Controllerクラスのプロパティhogeにアクセスさせてます。
class MenuBarController(){
var controller : Controller by Delegates.notNull()
FXML fun hoge(event: ActionEvent) {
println(controller.hoge)
}
}
相互にコントローラーを参照しているので、お互いのメソッドを呼び合うことができます。
あまりにコントローラーで参照しあうと複雑になりそうですが、2階層程度ならなんとかなりそうですね。
