I am trying to build my first 'real' application with java using JavaFX. I'm using FXML to design the whole thing and so I decided to divide up some parts into different .fxml
files and link those to different controllers. I'm using one MainController
linked to main.fxml
, and within main.fxml
I call some other fxml files using fx:include
. All includes have their own controller.
The issue is that the controllers don't operate 100% independently, sometimes you want to press a button linked to one controller and have that so something to another controller. I have a solution that works, but I'm not sure if it is the best way to do it.
My solution is this: Have one abstract SubController
class, which has protected static fields for each of the subcontrollers. Upon initialization MainController
fills all of these fields with the controller classes it gets from main.fxml
, as well as one field for MainController
itself. Each of the sub-controllers inherit from SubController
so that they can access the static fields and call the public methods of the other controllers.
public abstract class SubController implements Initializable {
protected static MainController mainController;
protected static MenuBarController menuBarController;
protected static VideoPanelController videoPanelController;
public static void setMainController(MainController mainController) {
SubController.mainController = mainController;
}
public static void setMenuBarController(MenuBarController menuBarController) {
SubController.menuBarController = menuBarController;
}
public static void setVideoPanelController(VideoPanelController videoPanelController) {
SubController.videoPanelController = videoPanelController;
}
}
public class MainController implements Initializable {
@FXML private MenuBarController menuBarController;
@FXML private VideoPanelController videoPanelController;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
SubController.setMainController(this);
SubController.setMenuBarController(menuBarController);
SubController.setVideoPanelController(videoPanelController);
}
This way when a button is clicked in the menu bar, it can use a public method of the video panel controller:
public class MenuBarController extends SubController {
public void openVideo() {
File selectedFile = chooseFiles(VIDEO_EXTENSIONS);
if (selectedFile == null) return;
videoPanelController.loadVideo(selectedFile);
}
}
This works quite well, but I still feel like there's probably an easier way to do it. Is this a good way to go about it and if not, how else should I do it?