JavaFX Daten zwischen Controllern austauschen- neue Frage

ralfb1105

Bekanntes Mitglied
Hallo zusammen,

in dem Thread https://www.java-forum.org/thema/daten-zwischen-controller-austauschen.183928/ habt Ihr mir hier im Forum seh anschaulich und gut erklärt wie ich von meinem Main Controller weitere Controller aufrufen kann und in diesen dann auf Objekte des Main Controller zugreifen kann --> ControllerInjectable, ControllerFactory und ViewLoader. Dieses Framework habe ich jetzt auch schon erfolgreich in meinem projekt implementiert.

Nun habe ich festgestellt das ich quasi auch noch "die andere Richtung" benötige, soll heißen ich muss von meinem MainController auf Objekte des aufgerufenen Controller zugreifen.

Um es deutlicher zu machen hier mein aktuelles Problem:

Problembeschreibung:
Ich habe einen Controller und in dem wird über einen Button ein weiterer Controller aufgerufen. Hier das Code Beispiel:
Java:
// Method for DB Monitor Button
    public void dbMonitorButtonTapped() {
        Parent rootDBMonitor = ViewLoader.load("DBMonitorView.fxml",
                clazz -> ControllerFactory.controllerForClass(clazz, model, db, this));
        Stage stageDBMonitor = new Stage();
        stageDBMonitor.initModality(Modality.NONE);
        stageDBMonitor.setOpacity(1);
        stageDBMonitor.setTitle("DB Monitor View");
        Scene sceneDBMonitor = new Scene(rootDBMonitor);
        sceneDBMonitor.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
        stageDBMonitor.setScene(sceneDBMonitor);
        stageDBMonitor.setOnCloseRequest(event -> {
            LOGGER.info("Close JavaFX Stage: ControllerDBMonitor");
        });
        LOGGER.info("Starting DB Monitor window @ SID " + getDbSid());
        messageTextArea.appendText("Starting DB Monitor window @ SID " + getDbSid() + "\n");
        stageDBMonitor.show();
    }
In dem neuen Controller wird unter anderem eine Datenbank Verbindung in der Initialize() Methode erstellt:
Java:
// Create DB connection
        try {
            connSys = db.dbConnect(controller.getConnectString(), controller.getDbSysUser(),
                    controller.getDbSysUserPassword());
        } catch (Exception ex) {
            String msg = String.valueOf(ex);
            controller.messageTextArea.appendText(msg + "\n");
            LOGGER.severe(msg);
            ((Stage) chart.getScene().getWindow()).fireEvent(
                    new WindowEvent(((Stage) chart.getScene().getWindow()), WindowEvent.WINDOW_CLOSE_REQUEST));
        }
Das Fenster hat nur ein AreaChart, sonst nichts.
Wenn ich nun als Benutzer dieses neue Fenster schließe habe ich keine Möglichkeit innerhalb des ControllerDBMonitor die Datenbank Verbindung zu schließen, was natürlich schlecht ist!

Nun habe ich ja in meinem Main Controller in der Button Methode ein Event erstellt, welches ausgeführt wird wenn es ein setOnCloseRequest gibt:
Java:
stageDBMonitor.setOnCloseRequest(event -> {
            LOGGER.info("Close JavaFX Stage: ControllerDBMonitor");
        });

Aus meiner Sicht wäre das ja eine gute Stelle um beim schließen des Fenster die Verbindung zu schließen. Nun habe ich aber folgendes Problem:
1. Ich habe keinen Zugriff auf das Connection Objekt aus dem ControllerDBMonitor.
2. Wenn ich mir im MainController eine Instanz von der Klasse ControllerDBMonitor erstelle und dann mit Hilfe von Getter/Setter versuche auf das Objekt zuzugreifen, gibt es eine NPE. Meine Vermutung ist das dieses Objekt dann nicht mehr verfügbar ist .. ??

Frage:
Wie kann ich die Datenbank Verbindung schließen (connSys.close()) wenn das Fenster geschlossen wird?

Kann ich irgendwie in dem ControllerDBMontor einen "Listener" konfigurieren der beim schließen des Fenster noch Aktionen ausführt?

Gruß
Ralf
 

dzim

Top Contributor
Nun ja, es ist ja nicht beschränkt, was du in deinen Controller reinreichen kannst. Das Connection-Objekt sollte es natürlich nicht sein, aber du kannst ja in deinem Model ein BooleanProperty (o.ä.) setzen und an geeigneter Stelle auf diese Änderung hören und dann darauf reagieren.

So etwas wie folgender (Pseudo-)Code:
Code:
// Controller:
model.setChartWindowClosed(true);

// Listener:
model.chartWindowClosedProperty().addListener((obs, o, n) -> {
  if (n != null && n)
    connection.close();
});

In etwa klar, was ich meine?
 

ralfb1105

Bekanntes Mitglied
Hallo Daniel,

leider ist mir nicht 100% klar was Du in Deinem Pseudo-Code machst. Ich hatte mir gestern Abend noch genau das überlegt, was Du vermutlich als schlecht zitierst :confused:
Nun ja, es ist ja nicht beschränkt, was du in deinen Controller reinreichen kannst. Das Connection-Objekt sollte es natürlich nicht sein
Ich hatte mir überlegt in meinem Main Controller folgendes zu implementieren:
Java:
private Connection connSysMonitor;
private Timeline animationDBMonitor;

public Connection getConnSysMonitor() {
        return connSysMonitor;
    }

    public void setConnSysMonitor(Connection connSysMonitor) {
        this.connSysMonitor = connSysMonitor;
    }
  
    public Timeline getAnimationDBMonitor() {
        return animationDBMonitor;
    }

    public void setAnimationDBMonitor(Timeline animationDBMonitor) {
        this.animationDBMonitor = animationDBMonitor;
    }

Im ControllerDBMonitor setze ich dann beim erstellen der Objekte Connection und Timeline diese im Main Controller über die Setter Methode:
Java:
public void initialize()  {
        controller.setAnimationDBMonitor(animation);
...
...
// Create DB connection
        try {
            connSys = db.dbConnect(controller.getConnectString(), controller.getDbSysUser(),
                    controller.getDbSysUserPassword());
controller.setConnSysMonitor(connSys);
...
...

Im Main Controller wird dann beim setOnCloseRequest Event folgendes ausgeführt:
Java:
stageDBMonitor.setOnCloseRequest(event -> {
            LOGGER.info("Close JavaFX Stage: ControllerDBMonitor");
            try {
                getConnSysMonitor().close();
                getAnimationDBMonitor().stop();
            } catch (SQLException e) {
              
            }
        });

Bei einem ersten kurzen Test scheint das im Prinzip auch zu funktionieren, vermute aber, auf Grund Deines Kommentars, das man es es genau so NICHT macht o_O

Somit würde ich gerne verstehen was Du in Deinem Paseudo Code machst ...

Ich müsste also im Model ein BooleanProperty Objekt erstellen und eine Methode setChartWindowClosed:
Java:
public BooleanProperty chartWindowClosedProperty = new SimpleBooleanProperty(false);

public void setChartWindowClosed(boolean value) {
        chartWindowClosedProperty.set(value);
    }

Die Zeile zu dem Listener ist mir im Detail
Java:
(obs, o, n) -> {
    if (n != null && n) {
nicht wirklich klar o_O
Ich habe es mal folgendermaßen versucht zu implementieren:
== Main Controller ==
Java:
stageDBMonitor.setOnCloseRequest(event -> {
            LOGGER.info("Close JavaFX Stage: ControllerDBMonitor");
            model.setChartWindowClosed(true);
        });
== ControllerDBMonitor ==
Java:
public void initialize() {      
        model.chartWindowClosedProperty.addListener((obs, o, n) -> {
            if (n != null && n) {
                animation.stop();
                try {
                    connSys.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });
...
...

Ein erster schneller Test sieht vielversprechend aus :)

Ist es das was Du mit Deinem Pseudo-Code ausdrücken wolltest?
Ist meine Implementierung so in etwas OK?

Danke auf jedem Fall schon mal für deine Hilfe!!

Gruß
Ralf
 

dzim

Top Contributor
Genau!
Haste doch richtig was draus gemacht! ;)

Warum ich die connection angesprochen habe: Um sauber zu programmieren, solltest du bestimmte Logik nicht vermischen. Das UI sollte nicht auf so spezielle Sachen wie DB-Connection schliessen zugreifen. Denn eigentlich hat man so etwas wie ein DAO (DataAccessObject) über das man DB-Zugriffe händelt, dass aber die konkrete Implementierung verbirgt. Es ist hier aber schon ok, so etwas wie #close oder #dispose also Methode zu haben.

Ich denke, du hast aus meinen wenigen Stichworten das Beste gemacht! Tip Top.
 

ralfb1105

Bekanntes Mitglied
Hallo Daniel,

Danke für Dein Kompliment :D und die zusätzlichen Erklärungen.
Leider habe ich nach dem ich es implementiert habe bei den Tests ein Problem festgestellt :(
Wenn ich in meinem UI den Button für den Monitor drücke wird die Connection aufgebaut und für diese Connection auch der Listener hinzugefügt. Schließe ich das Monitor Fenster wird die Verbindung auch geschlossen -> Kontrolle in der DB ;). Wenn ich nun in meinem UI noch einmal den Button für den DB Monitor drücke wird dieser wieder angezeigt und eine neue Verbindung aufgebaut -> unterschiedliche Session ID in der DB.
Problem:
Wenn ich das Fenster jetzt schließe wird die Verbindung leider nicht abgebaut. Ich vermute es liegt daran das ich schon einen Listener habe, bzw. es jetzt zwei Listener gibt ??

Hast Du eine Idee was ich falsch mache oder wo der Gedankenfehler liegt .. muss ich beim schließen den Listener wieder entfernen?

Gruß

Ralf
 

ralfb1105

Bekanntes Mitglied
Hallo Daniel,

ich habe mal ein bisschen probiert und sysout's hinzugefügt und verstehe es nicht wirklich.
Ich lasse mir beim addListener() den Wert für 'obs' ausgeben.
Das Ergebnis:
1. Starte UI
2. Drücke Button "Monitor"
Ausgabe: BooleanProperty [value: true]
3. Schließe Fenster "Monitor" -> DB Verbindung und Animation werden gestoppt.
4. Drücke Button "Monitor"
Ausgabe: -Keine-
5. Schließe Fenster "Monitor" -> DB Verbindung beliebt offen und Animation läuft weiter!?

Es sieht für mich so aus als wenn der Listener beim 2. Mal gar nicht hinzugefügt wird ... die initialize() Methode wird ja auf jeden Fall gestartet, denn sonst ginge ja gar nichts in dem Fenster.

Bis jetzt verstehe ich das nicht ...

Gruß
Ralf
 

ralfb1105

Bekanntes Mitglied
Hallo Daniel,

Typischer Anfängerfehler :mad: ich hatte vergessen das BooleanProperty beim starten der Stage auf false zu setzen. Da ich ja nur eine Model Instanz habe, was auch gut ist ;) blieb der BooleanProperty nach dem schließen des Fenster auf true und somit wurde nichts ausgeführt
Java:
if (n != null && n)

Ich habe jetzt in der Methode zum starten des Monitor noch folgendes hinzugefügt:
Java:
model.setDBMonitorWindowClosed(false);
stageDBMonitor.show();
und jetzt sieht es nach den ersten Tests gut aus :)

Gruß
Ralf
 

dzim

Top Contributor
Ich habe es erst jetzt gelesen und wollte gerade sagen, dass du das Flag auch "resetten" musst... Hast du aber schon wieder in der Zwischenzeit selbst hinbekommen. ;)
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
S JavaFX (Best Practise) Daten zwischen Controllern austauschen AWT, Swing, JavaFX & SWT 1
ralfb1105 JavaFX Daten zwischen Controller "austauschen" AWT, Swing, JavaFX & SWT 65
B Datenübergabe zwischen Tabs und Daten speichern AWT, Swing, JavaFX & SWT 2
A Daten umherschieben zwischen zwei Klassen AWT, Swing, JavaFX & SWT 40
H JTabel - RowFilter Daten für Berechnung filtern AWT, Swing, JavaFX & SWT 6
M Daten zufällig Einlesen aus einer Datei (binäres Format) AWT, Swing, JavaFX & SWT 7
W Nullpointer Exception beim übertragen von Daten von Scene zu Scene AWT, Swing, JavaFX & SWT 6
W Daten von Controller zu Controller übertragen AWT, Swing, JavaFX & SWT 7
D Columns unabhängig voneinander mit Daten füllen JavaFx AWT, Swing, JavaFX & SWT 1
H Daten aus einer XML(x83-Datei) in einem JFrame anzeigen lassen AWT, Swing, JavaFX & SWT 9
T Anbinden der Tabelle an die Daten AWT, Swing, JavaFX & SWT 5
F JavaFX Tabelle mit Daten füllen AWT, Swing, JavaFX & SWT 9
A JavaFX Daten in eine HTML-Table mit JS schreiben AWT, Swing, JavaFX & SWT 3
B AWT Bot um Daten auf Website einzugeben und die Antwort zu bekommen AWT, Swing, JavaFX & SWT 2
L Daten bearbeiten ohne GUI zu blockieren - daten haltung/zurück geben AWT, Swing, JavaFX & SWT 15
ralfb1105 Swing JComboBox update der Daten AWT, Swing, JavaFX & SWT 8
ralfb1105 Swing Dynamischer Graph zum anzeigen Perfomance Daten AWT, Swing, JavaFX & SWT 35
D MySQL Daten in JTable anzeigen AWT, Swing, JavaFX & SWT 2
K TreeTableView (cellFactory) - wie Daten in Spalten einfügen AWT, Swing, JavaFX & SWT 0
A JTable mit Daten füllen AWT, Swing, JavaFX & SWT 1
J TableView Daten werden nicht ausgegeben AWT, Swing, JavaFX & SWT 9
A Swing Wie Daten in der Form speichern? Array oder ArrayList AWT, Swing, JavaFX & SWT 2
C Swing Daten in JTable wiedergeben per TableModel und MVC Pattern AWT, Swing, JavaFX & SWT 16
T JavaFX Model Daten übergeben AWT, Swing, JavaFX & SWT 4
D Swing Größe einer JComboBox im GridBagLayout aufgrund der maximalen Länge der enthaltenen Daten AWT, Swing, JavaFX & SWT 7
J JavaFX Tableview Daten hinzufügen aus anderer Klasse AWT, Swing, JavaFX & SWT 7
J Tableview Daten hinzufügen und aktualisieren AWT, Swing, JavaFX & SWT 5
S AWT Daten über TextField und Button in array speichern AWT, Swing, JavaFX & SWT 5
G Event Handling TableView daten in ein neues Fenster herauslesen? AWT, Swing, JavaFX & SWT 3
thet1983 JavaFX TableView Objekt Daten anzeige AWT, Swing, JavaFX & SWT 2
L JavaFX Verzögerung beim Laden von Daten AWT, Swing, JavaFX & SWT 6
L Daten in neuem Fenster AWT, Swing, JavaFX & SWT 2
Tort-E JavaFX Daten an WebView Komponente AWT, Swing, JavaFX & SWT 1
I JTable: Doppelklick auf Table soll neues Fenster öffnen und Daten aus JTable anzeigen AWT, Swing, JavaFX & SWT 4
S JTable Daten aus Array AWT, Swing, JavaFX & SWT 9
M Java FX Daten an Controller übergeben AWT, Swing, JavaFX & SWT 3
S JList ist leer, aber DefaultListModel hat die Daten? AWT, Swing, JavaFX & SWT 9
M JavaFX Von FXML-Controllerdatei Daten zurückgeben AWT, Swing, JavaFX & SWT 6
F JavaFX Daten aus Tabelle in ComboBox AWT, Swing, JavaFX & SWT 9
B Swing JTable mit Daten - Reihen-Größe anpassen AWT, Swing, JavaFX & SWT 0
D Applet GWT speichert Daten nicht in Datenbank AWT, Swing, JavaFX & SWT 2
S SWT In Listen den Einträgen Daten zuordnen AWT, Swing, JavaFX & SWT 2
T SWT Table (mit Spinner Spalte) Daten auslesen AWT, Swing, JavaFX & SWT 4
F Swing JTable: Daten voreinstellen AWT, Swing, JavaFX & SWT 4
B Daten in eine JTable schreiben AWT, Swing, JavaFX & SWT 3
H Swing JfreeChart aktualisieren - mit daten aus thread AWT, Swing, JavaFX & SWT 3
J valueChanged()-Methode liefert unbrauchbare Daten AWT, Swing, JavaFX & SWT 4
D SWT TreeViewer: Daten aus Model gelöscht... trotzdem noch im Baum AWT, Swing, JavaFX & SWT 4
D Daten von JDialog an JTable in JFrame übergeben AWT, Swing, JavaFX & SWT 7
O JTable zeigt die alte Daten wieder AWT, Swing, JavaFX & SWT 23
H JTable zeigt keine Daten an AWT, Swing, JavaFX & SWT 5
M Swing Daten von JPanel zu JFrame senden AWT, Swing, JavaFX & SWT 13
C Swing JTable Daten einfügen AWT, Swing, JavaFX & SWT 6
Ollek IndexOutOfBoundsException bei neuen Daten in JTable AWT, Swing, JavaFX & SWT 13
J Swing JTable-Daten Speichern und bei zeilen-änderung beibehalten. AWT, Swing, JavaFX & SWT 6
L [SWT] Daten und Bilder drucken AWT, Swing, JavaFX & SWT 2
M Trotz richtiger Daten, falsches Bild wird gezeichnet?! AWT, Swing, JavaFX & SWT 4
O JFrame: Daten alle paar Sekunden aktualisieren AWT, Swing, JavaFX & SWT 3
C Daten aus DB -> JTable aktualisieren klappt nicht AWT, Swing, JavaFX & SWT 16
A Swing(Daten zugreifen) AWT, Swing, JavaFX & SWT 25
S JComboBox - veränderliche Daten AWT, Swing, JavaFX & SWT 6
T Daten mittels ComboBox in ein JTable adden AWT, Swing, JavaFX & SWT 7
Ollek Realisierung: JTable zur Laufzeit mit neuen Daten füllen AWT, Swing, JavaFX & SWT 3
GianaSisters Swing jTable Daten unsichtbar AWT, Swing, JavaFX & SWT 12
T JTree Daten in DB schreiben am besten SQL AWT, Swing, JavaFX & SWT 21
W Daten auf Textfeld in anderer Klasse verwenden AWT, Swing, JavaFX & SWT 4
T Daten der gesamten Woche anzeigen AWT, Swing, JavaFX & SWT 2
D Problem mit JFileChooser -> Daten werden mit anführungsstriche in JTable geschrieben AWT, Swing, JavaFX & SWT 8
H JList zeigt die Daten aus dem Array nicht an! AWT, Swing, JavaFX & SWT 13
E Daten von JDialog nach JFrame übertragen AWT, Swing, JavaFX & SWT 4
K TableModel mit Daten aus Datenbank füllen AWT, Swing, JavaFX & SWT 7
M JTree mit eigenen Knoten - Zugriff auf Daten AWT, Swing, JavaFX & SWT 6
L Swing Daten in JTable aktualisieren AWT, Swing, JavaFX & SWT 5
H Swing Tabelle nach Klick auf Button mit Daten füllen? AWT, Swing, JavaFX & SWT 2
B Swing JList Daten löschen AWT, Swing, JavaFX & SWT 13
R Swing XML Datei in JTree, Problem mit Daten einlesen AWT, Swing, JavaFX & SWT 34
A SWT: Daten in Raster mit Gitternetzlinien darstellen AWT, Swing, JavaFX & SWT 7
C Swing JTextField-Daten über mehrere Dialoge AWT, Swing, JavaFX & SWT 18
K TableModel Daten übergeben AWT, Swing, JavaFX & SWT 9
Milady Swing Änderung von Daten mit sql AWT, Swing, JavaFX & SWT 2
J Daten aus einer Textdatei in ArrayList holen AWT, Swing, JavaFX & SWT 9
X Swing Daten aus Vector ins TableModel ?? AWT, Swing, JavaFX & SWT 12
T Swing Liste von Daten anzeigen AWT, Swing, JavaFX & SWT 4
S Swing Daten aus Datenbank in JTable AWT, Swing, JavaFX & SWT 2
E JCombobox mit Daten aus DB füllen AWT, Swing, JavaFX & SWT 9
L Daten werden in JTable nicht angezeigt:( AWT, Swing, JavaFX & SWT 6
Milady Annzeigen alle Daten aus der Tabelle AWT, Swing, JavaFX & SWT 6
P Swing Liste von Daten auf JFrame AWT, Swing, JavaFX & SWT 6
E Daten aus sortierter Tabelle lesen AWT, Swing, JavaFX & SWT 2
X Swing JList -> Daten anders darstellen als im Model hinterlegt -> möglich ? AWT, Swing, JavaFX & SWT 9
X Doppelte Daten in DefaultListModel unterbinden AWT, Swing, JavaFX & SWT 3
ModellbahnerTT SWT Daten zur nächsten WizardPage senden AWT, Swing, JavaFX & SWT 4
J Daten in JTable nach Sortierung auslesen AWT, Swing, JavaFX & SWT 2
hdi Swing JTable & Filtern: Daten nicht in der View AWT, Swing, JavaFX & SWT 2
S JTable Bug - eingegebene Daten werden falsch geparst :( AWT, Swing, JavaFX & SWT 4
L AWT Daten vom Dialog an Frame senden AWT, Swing, JavaFX & SWT 3
hdi Swing JTable: Löschen vom Daten im Model AWT, Swing, JavaFX & SWT 7
U JTable mit Daten aus einer HashMap füllen AWT, Swing, JavaFX & SWT 8
S Swing Bei Klick auf OK Daten übergeben AWT, Swing, JavaFX & SWT 6
A Daten aus einem Frame werden im nächsten nicht gesehen AWT, Swing, JavaFX & SWT 17

Ähnliche Java Themen

Neue Themen


Oben