# JList, JTree, JTextarea - Daten"refresh"



## diggaa1984 (17. Mrz 2009)

hiho,

wie immer ein sehr toller titel 



*Ich stehe grad vor folgendem Problem:*

ich habe eine zentrale Datenklasse, welche vorerst eine ArrayList<Person> beinhaltet, wird später noch mehr dazu kommen.

Ich möchte die Daten dieser ArrayList nun auf versch. Komponenten verteilen und anzeigen. In einem JTable sehe ich so ziemlich alles an Personen-Eigenschaften. Dennoch würde ich zwecks Suche oder später auch im Sinne von Filtern einige Daten (z.B. Name, VName) in JLists oder JTrees abbilden.

Wie löse ich es nun am Besten, dass ich diese Komponenten alle aktuell halte (sprich Druck auf Toolbarbutton = neue Person .. impliziert neuer Eintrag in Tabelle, Liste etc.). Bisher habe ich die Tabelle als einzelnen Listener registriert, der Rest ist noch nicht da, aber würde es Sinn machen, an die 6-7 Swing-Komponenten als Listener an der Datenklasse zu registrieren, oder gibt es da andere üblichere Wege zentrale Daten(-änderungen) zu propagieren!?


----------



## SlaterB (17. Mrz 2009)

die Datenklasse bekommt schonmal gar keinen Listener,
die Datenklasse, sei es 'PersonList' oder nur eine ArrayList<Person>, wird einem neu definierten MetaPersonModel übergeben (idealerweise als Kopie),
dieses bekommt 6-7 Listener, aber eher keine Swing-Komponenten, sondern ListModel, TableModel usw,
diese haben dann jeweils ihre Swing-Komponenten JTable, JList usw. als einzelne Listener 

alternativ könnte man versuchen, das MetaModel diverse Interface (ListModel, TableModel usw) implementieren zu lassen


----------



## Wildcard (17. Mrz 2009)

Schreib dir Adapter, die dein Datenmodell auf Swing Interfaces adaptieren/übersetzen können. So musst du die Daten nur einmal halten und alles bleibt synchron. Es bietet sich zB eine AdapterFactory an.
Beispiel:
[HIGHLIGHT="Java"]ListModel listView = (ListModel)AdapterFactory.getAdapter(model,ListModel.class);[/HIGHLIGHT]


----------



## diggaa1984 (17. Mrz 2009)

aso ja, das mit dem models ist klar  war falsch ausgedrückt, aber was genau meinst mit 





> die Datenklasse, sei es 'PersonList' oder nur eine ArrayList<Person>, wird einem neu definierten *MetaPersonModel* übergeben (idealerweise als Kopie),



also meine Datenklasse hat eben die ArrayList, und ist zuständig für deren Mächtigkeit (neue Datensätze anlegen, löschen, etc.) .. also die Menge an Daten verwalten.
was wäre der Sinn einer weitere Äusseren klasse!? Die Actions der Buttons sind ja wie folgt (addPerson(...) .. deletePerson(...)) .. also die Actions rufen die Methoden der zentralen Datenklasse auf um die Mächtigkeit zu verändern. Eine nocht weiter oben angesiedelte Klasse würde die Aufrufe nur durchleiten, das wäre für mich nicht sinnvoll.

Oder habe ich einen gravierenden Nutzen übersehen?!


----------



## diggaa1984 (17. Mrz 2009)

Wildcard hat gesagt.:


> Schreib dir Adapter, die dein Datenmodell auf Swing Interfaces adaptieren/übersetzen können. So musst du die Daten nur einmal halten und alles bleibt synchron. Es bietet sich zB eine AdapterFactory an.
> Beispiel:
> [HIGHLIGHT="Java"]ListModel listView = (ListModel)AdapterFactory.getAdapter(model,ListModel.class);[/HIGHLIGHT]



das ist an sich eine feine Idee, dennoch hilft mir das nich beim Propagieren von Änderungen, oder? Wenn ich per Tollbar den Datensatz erweitere .. bekommen die ListModels und TabelModels dieses ja auch trotz Adapter nicht automatisch mit, wenn ich davon ausgehe,dass der Adapter nur die Konvertierung der Daten in geeignetes Format vornimmt. Also eine Art Notification muss ich rumschicken, frage ist eben nur wo ich diese dann in deiner Variante anbinden würde.

Ach seh grad, der Adapter könnte ja dann die Anmeldung als Listener vornehmen korrekt!?


----------



## Gast2 (17. Mrz 2009)

Reichen für sein Vorhaben nicht einfach die Klassen PropertyChangeListener und  PropertyChangeSupport?So wie ich das verstanden hab will er alle "Listener" benachrichtigen wenn sich irgendwas in seinen Daten geändert hat


----------



## Wildcard (17. Mrz 2009)

diggaa1984 hat gesagt.:


> Ach seh grad, der Adapter könnte ja dann die Anmeldung als Listener vornehmen korrekt!?


Korrekt, irgendeine Art von Notification Mechanismus sollte dein Datenmodell bieten (nach Möglichkeit aber nicht Swing spezifisch), das ist auch durchaus üblich.
Vielleicht wagst du auch mal einen Blick über den Tellerrand und verwendest ein EMF Modell anstatt dir selbst eins zu basteln. Das bietet dir unter anderem:

Databinding
Notification Support
Adapter Support
Adapter Factories
generische Präsentations und Edit Schicht
hält sich selbstständig konsistent
erweiterbar
und vieles mehr


----------



## Wildcard (18. Mrz 2009)

Ich habe nicht alles gelesen, aber dieser Artikel beschreibt eine solche Adapter Lösung mit einem EMF Modell beispielhaft für ein JLabel. Das 'text' Property eines JLabels wird per adapter an ein 'name' Feature eines EMF Objekts gebunden. Die gleiche Lösung lässt sich auf Tabellen, Listen, Bäume, SWT, JFace, AWT, Swing,... anwenden. Man braucht nur den passenden Adapter.
Sieht übrigens erstmal komplizierter aus als es in Wirklichkeit ist 
EMF ist allerdings definitiv eine Investition in die zukünftige Qualität deiner Software. Für mich eines *der* Java Tools schlechthin.
Exception


----------



## diggaa1984 (18. Mrz 2009)

hm wäre mal eine Überlegung wert die Datenstrukturen wie ich sie jetzt hab in einem 2. Projekt mittels EMF umzusetzen ... das ist ja schon ein kleiner Batzen der da mit einmal vor mir liegt und verstanden werden will


----------



## Wildcard (18. Mrz 2009)

Nach meiner Erfahrung ist die Haupteinsteigshürde bei EMF nicht das verwenden, sondern das akzeptieren, dass alles was man bisher händisch getan hat, automatisiert viel besser funktioniert und einem tatsächlich abgenommen wird.
Besonders wer aus der JAXB Ecke kommt, hat oft Probleme mit dem Konzept.
Beispiel :

```
Parent1
 +-Kind1
 +-Kind2

Parent2
 +-Kind3
```

EMF:
[HIGHLIGHT="Java"]parent2.getChildren().add(kind1);[/HIGHLIGHT]

Ergebnis:

```
Parent1
 +-Kind2

Parent2
 +-Kind3
 +-Kind2
```
Das generierte Modell besteht nicht nur aus stupiden, von zB JaxB bekannten Datencontainern. Stattdessen weiß es selbst, das ein Kind nur einen Parent haben darf und ändert daher alle Referenzen entsprechend.
Wer mal verstanden hat, das man sich um diese Details nicht mehr kümmern muss, da das Model sich am besten selbst verwalten kann, der wird EMF nicht mehr missen wollen.

Anderes Beispiel:
Das leidige Thema mit Listen. Gibt man sie nach aussen? Gibt man eine Kopie nach aussen? Gibt man eine Read-Only Sicht nach aussen? Macht man add und remove Methoden? Was ist wenn mal umsortiert werden soll? Alle Entfernen und neu einfügen?
Warum die Verenkungen? Weil man von Listen keine Notifications bekommt und das Modell in inkonsistene Zustände überführt werden kann.
EMF geht einen anderen Weg. Listen werden als echte Referenzen nach aussen gegeben, die einfachste Art die Daten zu manipulieren.
Aber alle Listen erweitern die Java Collections und sind nun in der Lage die Notification Chain bei Änderungen zu informieren, Referenzen upzudaten und Typen zu validieren (auch ohne Generics).
Sicher, man muss sich auf das Konzept einlassen und initial (ein wenig) Aufwand investieren, aber es zahlt sich meiner Meinung nach hundertfach wieder aus.


----------



## diggaa1984 (18. Mrz 2009)

> Das leidige Thema mit Listen. Gibt man sie nach aussen? Gibt man eine Kopie nach aussen? Gibt man eine Read-Only Sicht nach aussen? Macht man add und remove Methoden? Was ist wenn mal umsortiert werden soll? Alle Entfernen und neu einfügen?
> Warum die Verenkungen? Weil man von Listen keine Notifications bekommt und das Modell in inkonsistene Zustände überführt werden kann.



SIGN :toll:


----------



## SlaterB (18. Mrz 2009)

mein Gedanke war jedenfalls noch, durch Kopie eine Trennung zwischen in der GUI angezeigten und irgendwo intern verwalteten Personen zu ziehen,
das ist vielleicht nur bei mehreren Threads/ Usern/ Aktionen gleichzeitig relevant,

jedenfalls sollte ein add-Button-Klick, der vielleicht gar nur ein initial halb gefülltes Platzhalter-Element in die Liste einfügt, nicht gleich die wichtige Datenhaltung des ganzen Programms ändern


----------



## diggaa1984 (18. Mrz 2009)

SlaterB hat gesagt.:


> jedenfalls sollte ein add-Button-Klick, der vielleicht gar nur ein initial halb gefülltes Platzhalter-Element in die Liste einfügt, nicht gleich die wichtige Datenhaltung des ganzen Programms ändern



würde für mich nur Sinn ergeben, wenn im Anschluss daran ein Dialog aufgeht der einige grundlegende Infos editieren/setzen lässt. Wenn man ihn bestätigt wird die originale Datenstruktur erweitert, anderfalls nicht. 

Oder, wie du sagtest, wenn nebenläufige Zugriffe auf die Datenstruktur erfolgen, das kann ich allerdings komplett aussschließen. In dem Fall würde dann ein Thread, wenn er denn an der Reihe ist die Daten von der Kopie ins Original übernehmen, oder wie wäre das in deiner Vorstellung?


----------



## SlaterB (18. Mrz 2009)

neben der Tabelle ein 'Speichern'-Button, was auch immer das heißt ohne dass jetzt hier die Persistenz besprochen wurde


----------



## diggaa1984 (18. Mrz 2009)

ja gut, vergleichbar mit nem expliziten "commit" im svn oder das Starten einer Folge von Transaktionen (alle bisher durchgeführten Änderungen) zu einer DB .. aber in meinem Programm weniger notwendig


----------



## Wildcard (18. Mrz 2009)

diggaa1984 hat gesagt.:


> ja gut, vergleichbar mit nem expliziten "commit" im svn oder das Starten einer Folge von Transaktionen (alle bisher durchgeführten Änderungen) zu einer DB .. aber in meinem Programm weniger notwendig



Habe ich schon erwähnt das EMF Modelle Transaktionen, Queries und Undo/Redo unterstützen


----------

