やってみればなんてことはないんですが。
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階層程度ならなんとかなりそうですね。