A simple way is just to define the methods you need in each controller and call them from the event handler. In this case, your KnopfController
will need to call the textChange()
method in the main controller (so it needs a reference to the Controller
), and then textChange()
will call a method in the FeldController
.
So you would do something like this:
public class FeldController {
@FXML
private TextField textField ;
public void updateText(String text) {
textField.setText(text);
}
}
KnopfController
needs a reference to the "main controller", so it will need
public class KnopfController {
private Controller mainController ;
public void setMainController(Controller mainController) {
this.mainController = mainController ;
}
// button handler:
@FXML
private void handleButtonClick(ActionEvent event) {
mainController.textChange("Hello");
}
}
And now your main controller wires it all together:
public class Controller {
@FXML
private AnchorPane Main;
@FXML
private FeldController feldController;
@FXML
private KnopfController knopfController;
public void initialize() {
knopfController.setMainController(this);
}
public void textChange(String newText){
feldController.updateText(newText);
}
}
While this works, the design problem here is that you have tightly coupled the controllers (e.g. your KnopfController
depends on the Controller
class, which to some extent works against the idea of factoring it out into a separate FXML-controller pair in the first place). A better approach is to share a data model among the controllers, and update/observe the model.
E.g.:
public class Model {
private final StringProperty text = new SimpleStringProperty() ;
public StringProperty textProperty() {
return text ;
}
public final String getText() {
return textProperty().get();
}
public final void setText(String text) {
textProperty().set(text);
}
}
and now the basic idea is to do
public class KnopfController {
private Model model ;
@FXML
private void handleButton() {
model.setText("Hello");
}
}
and
public class FeldController {
@FXML
private TextField textField ;
private Model model ;
// ...
textField.textProperty().bindBidirectional(model.textProperty());
// ...
}
Of course, both these controllers need to have a reference to the same model instance for this to work, so you need to "inject" this into the controllers. You can do this just by creating setModel()
methods and calling them:
public class KnopfController {
private Model model ;
public void setModel(Model model) {
this.model = model ;
}
@FXML
private void handleButton() {
model.setText("Hello");
}
}
and for FeldController
you can do the binding when the model is set:
public class FeldController {
@FXML
private TextField textField ;
private Model model ;
public void setModel(Model model) {
this.model = model ;
textField.textProperty().bindBidirectional(model.textProperty());
}
}
Then your main controller just reduces to:
public class Controller {
private Model model ;
@FXML
private FeldController feldController;
@FXML
private KnopfController knopfController;
public void initialize() {
model = new Model();
knopfController.setModel(model);
feldController.setModel(model);
}
}
You can go one step further, and use a controller factory to provide the model to the controllers for you. I posted an example of doing that in a github repo. Note this is only proof-of-concept: to do DI like this you should probably use a framework for it - afterburner.fx provides a simple but flexible JavaFX DI framework (or you can use other, standard, frameworks such as Spring or Guice).