Zwei Ansätze hier.
Passing das Modell zu nested Controller
Sie können die Controller aus dem enthaltenen FXML in die Steuerung für die darunter FXML injizieren, um die nested controllers Technik. Dann kann der "äußere Controller" das Modell auf den "verschachtelten Controller" propagieren.
Also z.B. wenn Sie
<SplitPane xmlns="..." fx:controller="com.mycompany.MainController">
<items>
<TableView prefHeight="200.0" prefWidth="200.0">
<columns>
<TableColumn prefWidth="75.0" text="User" />
<TableColumn prefWidth="75.0" text="Pass" />
</columns>
</TableView>
<fx:include fx:id="container" source="Container.fxml"/>
</items>
</SplitPane>
Angenommen, der Controller-Klasse für Container.fxml
ContainerController
ist. Dann würden Sie tun:
public class MainController {
private Model model ;
@FXML
private ContainerController containerController ; // name is fx:id with "Controller" appended
public void setModel(Model model) {
this.model = model ;
containerController.setModel(model);
// ...
}
// ...
}
und natürlich
public class ContainerController {
private Model model ;
public void setModel(Model model) {
this.model = model ;
// ...
}
// ...
}
einen Controller Factory Mit
Wenn Sie eine Menge enthalten FXML Dateien und Controller haben, etc, kann diese beginnen wartbaren zu bekommen . In diesem Fall könnte es besser sein, das Modell in den Konstruktoren der Controller zu initialisieren und controllerFactory
auf FXMLLoader
zu verwenden, um Controller mit einem Modell zu erstellen, das an den Konstruktor übergeben wird. So, jetzt Sie Controller wie folgt aussehen:
public class MainController {
private final Model model ;
public MainController(Model model) {
this.model = model ;
}
public void initialize() {
// bind controls to model here...
}
}
und in ähnlicher Weise für ContainerController
usw. Hinweis: Dies ist viel sauberer als die vorherigen Versionen, wo man über das Modell zu einer beliebigen Zeit eingestellt Sorge musste zu werden. Hier ist garantiert, dass es gesetzt wird, wenn Code im Controller ausgeführt wird.
Jetzt müssen Sie ein wenig Magie für die FMXLLoader
die Controller korrekt erstellen, wenn die FXML geladen wird:
Model model = new Model();
FXMLLoader loader = new FXMLLoader(getClass().getResource("path/to/fxml"));
Callback<Class<?>, Object> controllerFactory = (Class<?> type) -> {
try {
for (Constructor<?> c : type.getConstructors()) {
if (c.getParameterCount() == 1 && c.getParameterTypes()[0].equals(Model.class)) {
return c.newInstance(model);
}
}
// couldn't find constructor taking a model, just use default:
return type.newInstance();
} catch (Exception exc) {
exc.printStackTrace();
return null ;
}
};
loader.setControllerFactory(controllerFactory);
Parent root = loader.load();
// ...
Beachten Sie, dass FXML Dateien über ein <fx:include>
-Tag geladen wird die gleiche Steuerung Fabrik wie die Verwendung " einschließlich "FXML-Datei. So wird das gleiche Modell automatisch an den verschachtelten Controller übergeben.
DI Mit Frameworks
Schließlich, wenn Sie wirklich viel dies tun, könnten Sie eine Abhängigkeit inject Rahmen zu prüfen, indem Sie die Abhängigkeiten auf dem Modell zu verwalten. Afterburner.fx ist ein dedizierter JavaFX DI Rahmen, und dann ist alles so einfach wie
public class MainController {
@Inject
private Model model ;
public void initialize() {
// bind UI elements to model...
}
}
Sie auch Frühling oder Guice verwenden können. Z.B. Konfigurieren Sie die Controller mit Spring als Prototyp-Beans, das Modell als Singleton-Bean, und schreiben Sie die Controller so, dass sie das Modell wie mit "afterburner.fx" injizieren. Dann können Sie ein FXMLLoader
sagen Frühling zu verwenden, um die Controller mit
// Spring application context:
ApplicationContext appContext = ... ;
FXMLLoader loader = new FXMLLoader(getClass().getResource("path/to/fxml"));
loader.setControllerFactory(appContext::getBean);
Parent root = loader.load();
Verwenden Sie einen MVC-Ansatz zu erstellen: ein Modell zwischen den beiden Controllern teilen und die Daten aus dem Modell zugänglich machen. Siehe http://stackoverflow.com/questions/32342864/applying-mvc-with-javafx –
Danke für Ihre ausführliche Anleitung und vollständigen Quellcode –
James_D Ein wenig gierig, aber ich habe noch eine Frage zum Thema erweiterte Datenupdates update a tableview von einem anderen FXML. Ich freue mich auf Ihre Hilfe: D –