JavaFX Frage zum FX-Loader

top_chief

Mitglied
Hallo,
mir ist folgendes aufgefallen...

Code 1 (funktioniert nicht):
"normale" Klasse:

Code:
private SettingsController mController;

private void initStage() {
        
        mController = new SettingsController();
        mController.setSettings(this);
        mController.setMain(mMain);
        FXMLLoader loader = new FXMLLoader(getClass().getResource("/app/fmxl/settings.fxml"));
        //...
}

private void foo() {
        mController.updateFontSize();
}

Code 2 (funktioniert):
Code:
private FXMLLoader mLoader;

    private void initStage() {
        SettingsController controller = new SettingsController();
        controller.setSettings(this);
        controller.setMain(mMain);
        mLoader = new FXMLLoader(getClass().getResource("/app/fmxl/settings.fxml"));
}

private void foo() {
       SettingsController controller = mLoader.getController();
       controller.updateFontSize(); 
}

Kann es sein, dass das ganze daran liegt, dass ich in meinen Settings eine Tab-Pane habe und deswegen der Controller seinen Zustand (nach der jeweiligen "Auswahl") verändert? Würde ungern mit dem Debugger die Zustände prüfen :-/ so empirisch möchte ich dann doch nicht arbeiten 😛

Gibt es irgendwo ein gutes Tutorial, oder ein Buch wo das mit dem Loader mal ausführlich erklärt ist? Oder findet sich hier jemand der mir die Funktionsweise des Loaders möglichst ausführlich erklären kann?

Ich habe schon unzählige Beitrage auf Stackoverflow durchgelesen, aber immer noch nicht das Gefüh, dass es "Klick" gemacht hat.

Danke vorab!
Martin
 
Was wäre im Code-Beispiel 1 deine Erwartungshaltung?

Konkret läuft es in JavaFX im Zusammenhang mit FXMLs und Controllern so, dass im XML die Controllerklasse bekannt gegeben wird. Wenn du nun mit FXMLLoader eine FXML lädst, parst dieser die Datei und sieht "aha, er möchte einen Controller der Klasse X" und erstellt entsprechend eine Instanz davon. Die weiter im XML definierte UI wird dann über die @FXML-Anntotationen an den Controller übergeben, damit dieser damit interagieren kann, bzw. Zugriff darauf hat.

Ich kann dir nichts anderen empfehlen, als zum einen die JavaDoc des FXMLLoaders anzuschauen und vielleicht zum anderen die Tutorials von Oracle selbst zu studieren.
Also:
Warum sollte ich es nutzen?
Unterschiede von JavaFX 2 zu JAvaFX 8 (hier wird auf einige Sachen vom FXMLLoader eingegangen).
...
 
Hallo dzim,
danke für deine Antwort. Ich glaube du hast mir damit schon sehr geholfen. Ganz sicher bin ich mir aber noch nicht, werde morgen mal ein kleines Testprogramm mit einer TabPane schreiben - habe gerade dort das Gefühl, dass Instanzen nicht geladen wurden (also dort in meinem Code verhältnismäßig viele Nullptrs entstehen)..

Wie trennst du deinen Code? Bzw. wann nutzt du die normale Klasse und wann den Controller?
Ich habe den Controller eigentlich nur in der Verwendung wenn der Nutzer (sehr) direkt mit der GUI interagiert (wahrscheinlich ist diese Beschreibung nicht wirklich aussagekräftig) onSliderChanged() oder onMouseMoved() wären typische Methoden, die ich im Controller abfrage. Aber insgesamt läuft es fast auf ein wildes Durcheinander heraus.
Habe aber auch schon FX-Code gesehen, der (wahrscheinlich) fast ausschließlich durch den Controller abgearbeitet wird... zB wird dort eine Scene mit folgendem Snippet mit Inhalt geladen:

Code:
class CustomerDialogController() {
  @FXML private Label customerName;
  void initialize() {}
  void initData(Customer customer) {
    customerName.setText(customer.getName());
  }
}
siehe hier ->dependency injection - Passing Parameters JavaFX FXML - Stack Overflow

Der Code dort erscheint mir als deutlich "schöner", aber irgendwie fehlt es mir an Wissen / Erfahrung, wie man eine Anwendung so sauber strukturiert. Hast du hierfür einen Tipp für mich?

Viele Grüße
Martin
 
Um Ehrlich zu sein, ist das eine nicht ganz einfach zu beantwortende Frage. Leider.

Wenn du den MVVM-Model folgst, ist dein Gedanke, was du im Controller machen möchtest, absolut richtig. Bzw. dort löst du dann Aktionen ausen, die das ViewModel ändern, die dann wiederum am Model selbst Änderungen auslösen.
Auch wenn ich MVVM grundsätzlich gutheisse, bin ich trotz reichlich Erfahrung auch nie ganz sicher, wo man hier die konkrete Linie wischen den einzelnen Komponenten zieht.

Ich selbst würde es zu Teilen auch wie in dem verlinkten StackOverflow Beitrag machen. Bzw. würde über Dependency Injection (welcher Art auch immer) zum Beispiel Data Access Objects hineinreichen, so dass der Controller nicht wissen muss, wie etwas funktioniert, sondern nur weitere Aktionen auslöst...
Viel Bla Bla und vieles bleibt am Ende dir überlassen (z.B. welche Form von Dependency Injection du wählst - setter-Methoden, @Inject-annotierte Variablen (hier: welches Framework), etc.).

Da muss ich also sagen: Finde deinen Stil, der idealerweise auch gut von anderen Verstanden werden kann... 🙂
 

Zurück
Oben