JavaFX ListView = null wenn ich sie in Laufzeit ändern will!

Davee

Mitglied
Moin,
Ich hab in diesem und auch schon in anderen Foren gesucht und mehr oder weniger auch was gefunden, aber das hat mir leider nicht wirklich weitergeholfen..

Es geht darum, dass ich eine Listview in Laufzeit ändern will. Durch einen Button werden Datensätze in eine Datenbank eingetragen. Das funktioniert auch, das Problem besteht darin, dass die Listview, die von mir dann den "Befehl" bekommt sich zu aktualisieren, indem sie das was neu in die Datenbank eingetragen wurde zusätzlich zu dem was sie schon beinhaltet hinzufügt, die Listview null ist. Wenn ich das Programm neu starte, wird der gleiche Code ausgeführt wie wenn ich einen neuen Datensatz hinzufügen will und komischerweise funktioniert das.

Nun habe ich schon verschiedene Ansätze gehört. Es liegt daran, dass JavaFX und die ListView Static sind und das nicht unterstützen oder sowas ähnliches. Ich weiß aber leider nicht mehr weiter. Ich werde ein wenig Code und Screenshots einfügen, vielleicht kann mir dann jemand helfen 🙂


[CODE lang="java" title="Das ist der Fehler" highlight="72"]javafx.fxml.LoadException:
/C:/Users/...

at javafx.fxml/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2625)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2603)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2466)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3237)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3194)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3163)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3136)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3113)
at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:3106)
at de.main.mainprogramController.addPassword(mainprogramController.java:52)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:76)
at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at javafx.base/com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:273)
at javafx.fxml/com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:83)
at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1784)
at javafx.fxml/javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1670)
at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics/javafx.scene.Node.fireEvent(Node.java:8879)
at javafx.controls/javafx.scene.control.Button.fire(Button.java:200)
at javafx.controls/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:206)
at javafx.controls/com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
at javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics/javafx.scene.Scene$MouseHandler.process(Scene.java:3851)
at javafx.graphics/javafx.scene.Scene$MouseHandler.access$1200(Scene.java:3579)
at javafx.graphics/javafx.scene.Scene.processMouseEvent(Scene.java:1849)
at javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2588)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:397)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:434)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:390)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:433)
at javafx.graphics/com.sun.glass.ui.View.handleMouseEvent(View.java:556)
at javafx.graphics/com.sun.glass.ui.View.notifyMouse(View.java:942)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: java.lang.NullPointerException: Cannot invoke "javafx.scene.control.ListView.getItems()" because "this.mpc.listview_pws" is null
at de.main.addPassword.newPassword.initialize(newPassword.java:30)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2573)
... 66 more[/CODE]

Das ist die addPassword Klasse, welche ausgeführt wird, wenn man in das Fenster kommt, wo man ein Password hinzufügen kann (Bild 3)addpw_listviewnull.PNG

Gleiches Bild wie oben, nur auskommentiert um die Funktionien zu erläutern.
addpw_listviewnull_nofehler.PNG

Bild 3: Hier kann man die Datensätze eintragen
addpwwindow.PNG


Das ist die Klasse mainProgramController die beim Start den gleichen Code ausführt wie oben (Bild 1 und 2). Hier funktioniert es auch.
mpc_liestviewnotnull.PNG



Das ist die Listview mit dem Button der uns zu Bild 3 führt.
listviewwithbutton.PNG
 
Code bitte immer in Code Tags und nicht als Bilder posten.

Und der Einblick dürfte noch nicht reichen. Was direkt auffällt ist, dass Du eine neue Instanz des Controllers erzeugst und in mpc speicherst.
Dadurch hast Du eine neue Instanz erzeugt, die losgelöst von jeder View ist, d.h. es hat hier keinerlei Zuweisung zu Feldern gegeben, die ein FXMLLoader machen würde.

Aus meiner Sicht deutet hier einiges darauf hin, dass Dein Code nicht wirklich gut strukturiert ist. Wenn Du mit @FXML Annotation und Injection arbeiten willst, dann musst Du z.B. mit dem FXMLLoader arbeiten und dann den dort erzeugten Controller nutzen.
 
Code bitte immer in Code Tags und nicht als Bilder posten.

Und der Einblick dürfte noch nicht reichen. Was direkt auffällt ist, dass Du eine neue Instanz des Controllers erzeugst und in mpc speicherst.
Dadurch hast Du eine neue Instanz erzeugt, die losgelöst von jeder View ist, d.h. es hat hier keinerlei Zuweisung zu Feldern gegeben, die ein FXMLLoader machen würde.

Aus meiner Sicht deutet hier einiges darauf hin, dass Dein Code nicht wirklich gut strukturiert ist. Wenn Du mit @FXML Annotation und Injection arbeiten willst, dann musst Du z.B. mit dem FXMLLoader arbeiten und dann den dort erzeugten Controller nutzen.

Danke für die Info, ja das ist eins meiner ersten größeren Projekte, kein wunder dass der Code unstrukturiert ist 😀 Aber danke für die Info, jedoch interessiert mich, wie ich mit dem FXMLLoader und dem dort erzeugten Controller arbeiten kann? Hast du da evtl ein Beispiel oder sowas?

Bis hierhin trotzdem danke erstmal 🙂
 
Also wenn Du eine Instanz von FXMLLoader hast, dann kannst Du per getController() dir den Controller geben lassen. Das setzt dann natürlich voraus, dass Du die Instanz von FXMLLoader hast.

Also angenommen, du hast Code wie:
Java:
Parent root = FXMLLoader.load(getClass().getResource("HelloWorld.fxml"));

das kann zu etwas gemacht werden wie:
Java:
FXMLLoader loader = new FXMLLoader(getClass().getResource("HelloWorld.fxml"));
Parent root = loader.load();
// loader.getController() kann nun aufgerufen werden.

Weitere Alternativen gibt es auch - man kann dem FXMLLoader auch eine Factory für den Controller mitgeben und so. In einem Model View Presenter Aufbau hatte ich schon gehabt, dass man nur einen Controller erzeugt hat. Der hat dann die View geladen und sich selbst als Controller mitgegeben wobei dann @FXML und so bearbeitet wurden ... Das geht jetzt aber vermutlich zu weit und das sollte erst einmal uninteressant sein.

Wichtig ist dann, dass Du Referenzen zu erzeugten Instanzen bekommen kannst um diese dann überall da vorzuhalten, wo Du diese brauchst.
 
Ja, diese Möglichkeit habe ich auch schonmal gesehen und ausprobiert, jedoch bin ich da auch nicht weitergekommen.
Ich habe Testweise mal diese Methode erstellt:
[CODE lang="java" title="Diese Methode wird ausgeführt wenn man einen Datensatz hinzufügen will"]public void add() throws SQLException, IOException {

FXMLLoader loader = new FXMLLoader(getClass().getResource("../main/mainprogram.fxml"));
mainprogramController controller = loader.getController();
// Datensätze werden ausgelesen aus Textfeld
String account = pwadd_account.getText();
String passwort = pwadd_field.getText();
System.out.println(account + passwort);

try {
DatabaseHandler dh = new DatabaseHandler();


// List wird mit dem letzten Eintrag der Datenbank befüllt
ObservableList<String> list = FXCollections.observableArrayList(dh.getDBMap().get(dh.getDBSizeFromPaws()).toString());

// Listview wird befüllt aus ObservableList
controller.listview_pws.getItems().add(list.toString());
controller.listview_pws.refresh();

} catch (SQLException throwables) {
throwables.printStackTrace();
}

}[/CODE]

Leider wird hier gesagt, dass "controller" wieder null ist. Oder habe ich etwas bei der Verwendung falsch gemacht?
 
Das ist so vom Ablauf her auch gerade unverständlich. Kannst Du erst einmal sagen, was Du da genau machen willst?

Den FXMLLoader nutzt Du ja, wenn Du den Inhalt für ein Fenster oder so laden willst. D.h. es kommt auch ein load() Aufruf zum Einsatz um dann das Ergebnis in der Oberfläche einzubinden (z.B. in der primary Stage, also als Fensterinhalt).

Aber Du lädst nur das FXML um dann einen controller zu bekommen? Wo ist das Fenster dahinter und so?

Das wäre erst einmal der Punkt der etwas abfragt, was Du überhaupt machen willst.

Bezüglich contrller null: Wie sieht die fxml Datei aus? Hast Du da auch den controller mit angegeben?
 
Ja okay, hier gibt es wohl wirklich ein Verständnisproblem 😀 Sorry dafür.

Ich habe kurz mal eine Skizze gezeichnet um zu Veranschaulichen wie mein Programm momentan grob aufgebaut ist:
skizze.PNG

Es geht hierbei nur um "addPassword" und "mainProgramController".
Wenn ich den Button "insert" im Fenster "addPassword" drücke, werden Datensätze in die Datenbank eingetragen. Dann soll die ListView im Fenster "mainProgramController" automatisch aktualisiert werden.
Das Problem was ich hier habe ist, dass ich nicht auf die ListView in mainProgramController aus der Klasse addPassword zugreifen kann.

Ich habe das ganze mal mit einem weiteren Button ausprobiert:
Ein Button "refresh" in dem Fenster/Klasse mainProgramController.
Wenn ich diesen drücke, wird die ListView erfolgreich aktualisiert. Aus der Klasse addPassword, kann ich jedoch leider nicht darauf zugreifen.

Falls nun die Frage aufkommt, wieso ich zwei verschiedene Klassen habe, das liegt daran, dass die beiden Klassen Controller für die beiden Fenster sind.
 
Also im mainProgramController öffnst Du ein neues Fenster zur Eingabe von weiteren Daten. Diese sollen dann eingetragen werden in einer Datenbank / in dem mainProgramController angezeigt werden.

Da schwebt mir ein Vorgehen vor, das von den Controllern unabhängig ist. Ob und wie Daten angezeigt werden, ist dem eingabe-Fenster doch erst einmal egal und da sollte es auch keine Abhängigkeiten geben.

Du solltest also Klassen haben, die nur die Daten und die Logik darauf repräsentieren. Die Instanz(en) kennt dann mainProgramController und diese werden dann auch an addPassword weiter gegeben.

Das Model kann dann auch ein Observer Pattern implementieren, d.h. mainProgramController kann informiert werden, wenn sich am Model etwas ändert. Zur Not nimmt man da dann sogar auch direkt eine Klasse von javaFX, die das schon hat (also z.B. Oberservablelist von Elementen Deiner Klasse) - aber dann musst Du schauen, wie Du das mit der Datenbank noch machst.
 
Ich werde mir das Thema mit dem Eventbus im Laufe des Tages nochmal anschauen. Das mit dem Observable Pattern finde ich ein wenig kompliziert, liegt evtl. auch daran, dass ich jedes Mal merke wenn ich in solchen Foren unterwegs bin, wie wenig Ahnung ich dann doch von Java habe 😂 Trotzdem danke erstmal, ich melde mich nochmal wenn ich entweder die Lösung habe oder noch Fragen habe 🙂
 
Ich werde mir das Thema mit dem Eventbus im Laufe des Tages nochmal anschauen. Das mit dem Observable Pattern finde ich ein wenig kompliziert, liegt evtl. auch daran, dass ich jedes Mal merke wenn ich in solchen Foren unterwegs bin, wie wenig Ahnung ich dann doch von Java habe 😂 Trotzdem danke erstmal, ich melde mich nochmal wenn ich entweder die Lösung habe oder noch Fragen habe 🙂
Ich denke, wenn man UI baut sollte man Observable Pattern schon mal gemacht haben oder zumindest das was schon gegeben ist wiederzuverwenden. In JavaFX ist das ziemlich stark vertreten mit Databinding, was ich auch verdammt cool finde.

Guckst dir mal bei Gelegenheit an, ansonsten EventBus ist ziemlich einfach benutzen.
 
Also das Observable Pattern hast du schon genutzt, wenn du eine ObservableList erstellst und bei einem Control setItems aufrufst.

Mehr steckt da erst einmal nicht drin. Und so eine Observable List kannst du von mehreren Klassen aus nutzen und verändern - so du einfach die Referenz weiter gibst.

Mehr steckt da erst einmal gar nicht dahinter.
 
Also das Observable Pattern hast du schon genutzt, wenn du eine ObservableList erstellst und bei einem Control setItems aufrufst.

Mehr steckt da erst einmal nicht drin. Und so eine Observable List kannst du von mehreren Klassen aus nutzen und verändern - so du einfach die Referenz weiter gibst.

Mehr steckt da erst einmal gar nicht dahinter.
Ja stimmt in dem Fall updated die UI automatisch sobald die ObservableList sich ändert. Aber wenn man das selber machen sollte, da steckt dann schon ein bisschen mehr Tipparbeit.
 
Also ich habe mir beide Varianten angeschaut und habe echt keinen Ansatz wie ich das machen soll 🙁
Ich habe mir das Thema Observal Pattern angeschaut und auch mal eine Möglichkeit einen ObservableList Listener zu erstellen (was nicht geklappt hat) und komme wieder nicht weiter.
Könnte mir jemand einen Ansatz zum Observal Pattern geben?
Ich poste nochmal meinen Code der 2 wichtigsten Klassen um die es geht.

Das ist das Hauptfenster auf der auch die ListView ist:

[CODE lang="java" title="Klasse mainprogramController"]package de.main;

import [...]

public class mainprogramController implements Initializable {
@FXML
private Button addpassword_button;

// noch public, da ich etwas ausprobiert habe
@FXML
public ListView<String> listview_pws;
public ObservableList<String> list;


@Override
public void initialize(URL url, ResourceBundle rb) {

try {

// Datenbankhandler Objekt wird erstellt
DatabaseHandler dh = new DatabaseHandler();

// Erster Datensatz wird aus Datenbank ausgegeben
System.out.println(dh.getDBArray(1));

// For-Schleife die so lange geht, wie die Datenbank groß ist
for (int i = 1; i <= dh.getDBSizeFromPaws(); i++) {

// List wird befüllt aus HashMap welche Daten aus Datenbank bekommt
ObservableList<String> list = FXCollections.observableArrayList(dh.getDBMap().get(i).toString());

// Listview wird befüllt aus ObservableList
listview_pws.getItems().add(list.toString());

// Listview wird erfolgreich ausgegeben
System.out.println(listview_pws.getItems().toString());
}

} catch (SQLException e) {
e.printStackTrace();
}
}


// aufruf des neuen Fensters
public void addPassword() {

try {

AnchorPane root = FXMLLoader.load(getClass().getResource("addPassword/newPassword.fxml"));
Scene scene = new Scene(root, 400, 400);
//scene.getStylesheets().add(getClass().getResource("mainapplication.css").toExternalForm());
Stage stage = new Stage();
stage.setScene(scene);
stage.setResizable(false);
stage.setMinHeight(1000);
stage.setMinWidth(1920);
stage.show();

} catch (IOException e) {
e.printStackTrace();
}
}

// Methode wird auf Knopfdruck aufgerufen
public void refreshList() {

try {

DatabaseHandler dh = new DatabaseHandler();

// List wird mit dem letzten Eintrag der Datenbank befüllt
ObservableList<String> list = FXCollections.observableArrayList(dh.getDBMap().get(dh.getDBSizeFromPaws()).toString());

// Listview wird befüllt aus ObservableList
listview_pws.getItems().add(list.toString());
listview_pws.refresh();

} catch (SQLException throwables) {
throwables.printStackTrace();
}
}


}
[/CODE]




Das ist das neue Fenster in dem man die Datensätze in die Datenbank hinzufügt:

[CODE lang="java" title="Klasse newPassword" highlight="29"]package de.main.addPassword;

import [...]


public class newPassword {

@FXML
private PasswordField pwadd_field;
@FXML
private TextField pwadd_account;


public void add() throws SQLException, IOException {

// Datensätze werden ausgelesen aus Textfeld
String account = pwadd_account.getText();
String passwort = pwadd_field.getText();

try {
DatabaseHandler dh = new DatabaseHandler();

// List wird mit dem letzten Eintrag der Datenbank befüllt (Unnötig, da aktualisierung hier nicht stattfindet)
ObservableList<String> list = FXCollections.observableArrayList(dh.getDBMap().get(dh.getDBSizeFromPaws()).toString());

// Datensätze werden in die Datenbank hinzugefügt (erfolgreich)
dh.addPasswordToPaws(account, passwort);

// TODO Hier soll die Listview aktualisierung EIGENTLICH stattfinden.
} catch (SQLException throwables) {
throwables.printStackTrace();
}

}
}
[/CODE]

Wenn man hier nun auf einen Knopf drückt, wird die Methode add() ausgeführt. Daten werden in die Datenbank eingetragen und EIGENTLICH soll dann direkt die einträge aus der Datenbank in die Observable List und dann in die ListView aus der vorigen Klasse eingetragen werden. Das funktioniert jedoch nicht, da die ListView aus Klasse 1 angeblich "null" ist, was ja daran liegt, dass ich ein Objekt erstellt habe. Das ganze bin ich umgangen indem ich in Klasse 1 (Hauptfenster) einen Button hinzugefügt hab, der direkt auf die ListView zugreifen kann und die ListView aktualisiert. Das funktioniert auch, jedoch soll das automatisch aus Klasse 2 funktionieren und nicht erst noch auf Knopfdruck. Das wäre ineffizient.
 
Also ich habe mir beide Varianten angeschaut und habe echt keinen Ansatz wie ich das machen soll 🙁
Ich habe mir das Thema Observal Pattern angeschaut und auch mal eine Möglichkeit einen ObservableList Listener zu erstellen (was nicht geklappt hat) und komme wieder nicht weiter.
Könnte mir jemand einen Ansatz zum Observal Pattern geben?
Ich poste nochmal meinen Code der 2 wichtigsten Klassen um die es geht.

Das ist das Hauptfenster auf der auch die ListView ist:

[CODE lang="java" title="Klasse mainprogramController"]package de.main;

import [...]

public class mainprogramController implements Initializable {
@FXML
private Button addpassword_button;

// noch public, da ich etwas ausprobiert habe
@FXML
public ListView<String> listview_pws;
public ObservableList<String> list;


@Override
public void initialize(URL url, ResourceBundle rb) {

try {

// Datenbankhandler Objekt wird erstellt
DatabaseHandler dh = new DatabaseHandler();

// Erster Datensatz wird aus Datenbank ausgegeben
System.out.println(dh.getDBArray(1));

// For-Schleife die so lange geht, wie die Datenbank groß ist
for (int i = 1; i <= dh.getDBSizeFromPaws(); i++) {

// List wird befüllt aus HashMap welche Daten aus Datenbank bekommt
ObservableList<String> list = FXCollections.observableArrayList(dh.getDBMap().get(i).toString());

// Listview wird befüllt aus ObservableList
listview_pws.getItems().add(list.toString());

// Listview wird erfolgreich ausgegeben
System.out.println(listview_pws.getItems().toString());
}

} catch (SQLException e) {
e.printStackTrace();
}
}


// aufruf des neuen Fensters
public void addPassword() {

try {

AnchorPane root = FXMLLoader.load(getClass().getResource("addPassword/newPassword.fxml"));
Scene scene = new Scene(root, 400, 400);
//scene.getStylesheets().add(getClass().getResource("mainapplication.css").toExternalForm());
Stage stage = new Stage();
stage.setScene(scene);
stage.setResizable(false);
stage.setMinHeight(1000);
stage.setMinWidth(1920);
stage.show();

} catch (IOException e) {
e.printStackTrace();
}
}

// Methode wird auf Knopfdruck aufgerufen
public void refreshList() {

try {

DatabaseHandler dh = new DatabaseHandler();

// List wird mit dem letzten Eintrag der Datenbank befüllt
ObservableList<String> list = FXCollections.observableArrayList(dh.getDBMap().get(dh.getDBSizeFromPaws()).toString());

// Listview wird befüllt aus ObservableList
listview_pws.getItems().add(list.toString());
listview_pws.refresh();

} catch (SQLException throwables) {
throwables.printStackTrace();
}
}


}
[/CODE]




Das ist das neue Fenster in dem man die Datensätze in die Datenbank hinzufügt:

[CODE lang="java" title="Klasse newPassword" highlight="29"]package de.main.addPassword;

import [...]


public class newPassword {

@FXML
private PasswordField pwadd_field;
@FXML
private TextField pwadd_account;


public void add() throws SQLException, IOException {

// Datensätze werden ausgelesen aus Textfeld
String account = pwadd_account.getText();
String passwort = pwadd_field.getText();

try {
DatabaseHandler dh = new DatabaseHandler();

// List wird mit dem letzten Eintrag der Datenbank befüllt (Unnötig, da aktualisierung hier nicht stattfindet)
ObservableList<String> list = FXCollections.observableArrayList(dh.getDBMap().get(dh.getDBSizeFromPaws()).toString());

// Datensätze werden in die Datenbank hinzugefügt (erfolgreich)
dh.addPasswordToPaws(account, passwort);

// TODO Hier soll die Listview aktualisierung EIGENTLICH stattfinden.
} catch (SQLException throwables) {
throwables.printStackTrace();
}

}
}
[/CODE]

Wenn man hier nun auf einen Knopf drückt, wird die Methode add() ausgeführt. Daten werden in die Datenbank eingetragen und EIGENTLICH soll dann direkt die einträge aus der Datenbank in die Observable List und dann in die ListView aus der vorigen Klasse eingetragen werden. Das funktioniert jedoch nicht, da die ListView aus Klasse 1 angeblich "null" ist, was ja daran liegt, dass ich ein Objekt erstellt habe. Das ganze bin ich umgangen indem ich in Klasse 1 (Hauptfenster) einen Button hinzugefügt hab, der direkt auf die ListView zugreifen kann und die ListView aktualisiert. Das funktioniert auch, jedoch soll das automatisch aus Klasse 2 funktionieren und nicht erst noch auf Knopfdruck. Das wäre ineffizient.
ich versteh das Problem nicht..du hast eine Observable List unbedingt überall benutzt...hast jedoch kein einziges binding benutzt...und du hast einen denkfehler beim aktualisieren...du willst nicht alles neu laden sondern nur die Änderungen an der Liste übernehmen

dh du brauchst die Referenz der Item Liste ...

Observer Liste = view.itemsListe
=> durch die Referenz werden Änderungen an deiner Liste auch an items vorgenommen weil es das gleiche Objekt ist...

du hast aber

view.items = Observer Liste

und da Ändern deine Änderungen nur 1 mal was weil du die Referenzen nicht ausnutzt



Es hilft nichts Observer ..Properties ... Referenzen zu haben wenn man die Objekte gleich weg wirft
so du einfach die Referenz weiter gibst.
wie von @kneitzel eig. schon mal erwähnt wurde
 
Zuletzt bearbeitet von einem Moderator:
Nun, ich habe meine eigene Lösung gefunden.

Das Hauptproblem bestand ja einfach darin, dass ich aus der einen Klasse nicht auf die Listview der anderen Klasse zugreifen konnte. Ich hab das einfach gelöst indem ich beide Klassen vereint habe und nun nur noch eine habe, somit funktioniert das refreshen der ListView.

Trotzdem Danke für eure Hilfe, ich bin mir sicher dass ich Observer Pattern und Eventbusse noch irgendwann brauchen werden 🙂
 

Zurück
Oben