Swing MVC in Projekt umsetzen

Wenn du, wie Informatiker das nunmal so machen, bei 0 zu zählen anfängst: Ja

😀 ..äh...ja :-D

Java:
extends DefaultPieDataset

Habs schonmal gemacht funktioniert erstmal beim befüllen zumindest super und das updaten sollte kein weiteres Problem werden. 🙂 wird langsam. Hoffe dass es dann auch einigermaßen akzeptabel ist 😉

Werde dann meinen Code evtl mal hochladen damit ihr mal drüber schauen könnt, vllt gibts ja paar No Go's... 😉
 
Ja, also in Anlehung an den oben verlinkten Beitrag wären da die Option 1 (also nicht 0) wohl einfacher: Das DefaultPieDataSet mit den Daten aus dem eigentlichen Modell füllen/aktualisieren, sobald das Modell ein PropertyChanged wirft. "Direkt" (durch delegation) PieDataSet zu implementieren würde auch gehen, wäre aber evtl. aufwändiger, weil man sich um das Übersetzen und Werfen der Events dann selbst kümmern müßte.
 
also ich habe nun von PieDataSet geerbt. Das wird initial befüllt dabei wird durch die rechnungen iteriert und der UMsatz pro Artikel errechnet. Bei jedem PropertyChangeEvent dass rechnungen betrifft update ich nun das PieDataSet. Um die UI Aktualisierung kümmert sich das DAtaSet selbst...coolerweise.

Ich wollte es deshalb nciht mit dem immer wieder neu setzen machen weil ich dann in der View die Iteration machen müsste und sowas und das habe ich nun in die geerbet modelklasse gepackt. sieht ca so aus:

Java:
public class UmsatzVerteilungsDefaultPieDataset extends DefaultPieDataset 
implements PropertyChangeListener {
	DisponentModel model;

	public UmsatzVerteilungsDefaultPieDataset(DisponentModel model) {
		this.model = model;
		this.model.getPropertyChangeSupport().addPropertyChangeListener(this);
		fillModel();
	}
	
	public UmsatzVerteilungsDefaultPieDataset(DisponentModel model,  KeyedValues data) {
		super(data);
		this.model = model;
		this.model.getPropertyChangeSupport().addPropertyChangeListener(this);
		fillModel();
	}

	private void fillModel() {
		Collection<Rechnung> billings =  this.model.getBillingList().values();
		
		Iterator<Rechnung> iter = billings.iterator();
		
		while (iter.hasNext()){
			Rechnung billing = iter.next();
			
			Iterator<Rechnungsposition> repos = billing.getRechnungsPositionen().iterator();
			
			while (repos.hasNext()) {
				Rechnungsposition repo = repos.next();
				if (this.getKeys()
						.contains(repo.getArtikel())) {
					this.setValue(
							repo.getArtikel(),
							this
									.getValue(repo.getArtikel())
									.doubleValue()
									+ repo.getGesamtPreis());
				} else {
					this.setValue(
							repo.getArtikel(), repo.getGesamtPreis());
				}
			}
		}		
	}
	@Override
	public void propertyChange(PropertyChangeEvent evt) { [...]
	}
	
}
 
Joa, sieht vernünftig aus. Ein Detail: Statt
Code:
Iterator<SomeClass> iterator = someCollection.iterator();
while (iterator.hasNext())
{
    SomeClass object = iterator.next();
    workWith(object);
}
kann man meistens (eben wenn man kein iterator.remove() machen muss) die foreach-Schleife verwenden
Code:
for (SomeClass object : someCollection)
{
    workWith(object);
}
 
Hallo. nochmal. Habe nun schon ne menge geschafft und habe folgende struktur:
Java:
DisponentModel_ImplBase (PropertyCHangeSUpport)
-->Disponent Model
-->Artikel
-->Hersteller
-->usw.

Controller (füllt model und sowas)


DisponentView (PropertyCHangeListener)

Nun ist es kein Problem einfach die view wird am Model als Listener angemeldet ich bekomme mit wenn jemand nen Artikel hinzufügt und so weiter...

Jetzt würde mich brennend interessieren wie ich es einrichte dass ich mitbekomme wenn sich ein Artikel geändert hat. Ich werde ja jetzt nicht daher gehen und jedem Artikel die View als PropertyCHangeListener übergeben oder? Also was hänge ich nun wie an die Artikel (Der Support ist eingerichtet)?

Hänge ich nun Disponent Model an Artikel und mappe die ganzen Changes in einen Change auf die View? ODer hänge ich die View jetzt an jeden einzelnen Artikel?

Ich danke im Voraus. HAbt mir schon extrem weiter geholfen. Steht schon recht viel im Moment.
 
nd nen Artikel hinzufügt und so weiter...
Jetzt würde mich brennend interessieren wie ich es einrichte dass ich mitbekomme wenn sich ein Artikel geändert hat. Ich werde ja jetzt nicht daher gehen und jedem Artikel die View als PropertyCHangeListener übergeben oder? Also was hänge ich nun wie an die Artikel (Der Support ist eingerichtet)?

immer das gleiche prinzip...
Code:
artikelModel.addChangeListener(new ProprtyChangeListener...)

Wo du das machst ist deine Sache du kannst es in der View adden in einem Controller der wiederum die View aktualisiert usw.
 
also ist es wirklich so dass ich immer wenn ich einen Artikel erstelle, also zb. beim initialen Model füllen bei jedem schleifendurchlauf durch das ResultSet sowas hier mache.

Java:
while (rs.next()) {

Artikel art = new Artikel();
art.getChangeSupport().addPropertyChangeListener(view); 
.....

}

ist das richtig? Und vor allem hält doch der COntroller keine referenz auf die view eigentlich oder? d.h. ich kan doch im COntroller garnicht "wirklich" den PropertyChangeListener da rein hängen...

Muss ich also im propertyCHange das geworfen wird wenn ein Artikel hinzugefügt wird diesem Artikel den Listener rein hängen!?
 
also ist es wirklich so dass ich immer wenn ich einen Artikel erstelle, also zb. beim initialen Model füllen bei jedem schleifendurchlauf durch das ResultSet sowas hier mache.

Java:
while (rs.next()) {

Artikel art = new Artikel();
art.getChangeSupport().addPropertyChangeListener(view); 
.....

}

ist das richtig? Und vor allem hält doch der COntroller keine referenz auf die view eigentlich oder? d.h. ich kan doch im COntroller garnicht "wirklich" den PropertyChangeListener da rein hängen...

Muss ich also im propertyCHange das geworfen wird wenn ein Artikel hinzugefügt wird diesem Artikel den Listener rein hängen!?

Naja eigentlich kümmert sich die View darum, was sie beobachten will?! Es können ja auch mehrere Views sein die den Artikel beobachten. Außerdem sind die Beobachter (ChangeListener) nicht nur Views es kann auch ein Controller auf Änderungen hören!!

Deine Struktur sieht auf jeden Fall falsch aus, da zuviele Schichten gemischt sind.
 
was meinst du denn jetztmit gemischt?

Habe es doch nun so gemacht wie du mir vorgeschlagen hast.

Domain model: Artikel, Rechnung, Hersteller (nur Datenklassen) ||||, Disponent Model (hält listen der Artikel, rechnung etc)
Controller: füllt model,...
GUIModel: TreeModel, ListModels, usw
GUIController: anonyme Listener und einzeln implementierte Listener etc.
GUI: nur View Code der die GUI Controller anbindet und referenz auf Contoller hat, CellRenderer, PropChangeListener

was is denn daran jetzt vermischt? UNd wie kann die View sich selbst bei jedem Artikel der erstellt wird (initial) anmelden wenn sie mit der befüllung ja eig ausser den PropertyChangeEvents die durch das Adden der Artikel zur Artikelliste ausgelöst werden?
 
Zuletzt bearbeitet:
was meinst du denn jetztmit gemischt?

Habe es doch nun so gemacht wie du mir vorgeschlagen hast.

Domain model: Artikel, Rechnung, Hersteller (nur Datenklassen) ||||, Disponent Model (hält listen der Artikel, rechnung etc)
Controller: füllt model,...
GUIModel: TreeModel, ListModels, usw
GUIController: anonyme Listener und einzeln implementierte Listener etc.
GUI: nur View Code der die GUI Controller anbindet und referenz auf Contoller hat, CellRenderer, PropChangeListener

was is denn daran jetzt vermischt? UNd wie kann die View sich selbst bei jedem Artikel der erstellt wird (initial) anmelden wenn sie mit der befüllung ja eig ausser den PropertyChangeEvents die durch das Adden der Artikel zur Artikelliste ausgelöst werden?

Hier hast du einen DB Zugriff und eine View in einer Klasse das ist gemischt.

Java:
while (rs.next()) {
 
Artikel art = new Artikel();
art.getChangeSupport().addPropertyChangeListener(view); 
.....
 
}

Irgendwas musst du doch mit den erzeugten Klassen machen???Die hängen doch nicht einfach in der Luft rum...
 
wie melde ich denn sonst beim erstellen des Artikels die View/ irgendeinen Controllr beim Artikel an?

Mein Disponenten Model hält listen aus Artikel, Rechnung, etc.,...

mein Controller greift auf di DB zu und erstellt diese Disponenten Model.

meine View bekomt controller und Model übergeben.--> View meldet sich beim Model als Listener an. (achtung hier meldet er sich nur für Änderungen an den Listen an) und das geht ja einfach so initial mit ein mal anmelden.

mein Model macht zb irgendwann mal...

setListData(model.getArtikelListe().toArray);

jetzt müsste das MOdel noch mtibekommen wenn sich artikel details ändern...also das Model am Artikel anmelden...Das ist jetzt die Frage wie das geht...So wie ich das oben geschrieben habe ist es ja im moment noch nciht.das wäre nur meine idee...also den Controller eine Referenz uf di View halten lassen (mit INterface PropertyChangeListener ( den müssen ja alles views die es dazu gibt haben)) und beim Model füllen einfach nru die referenzder View als Listener bei einzelnen Artikelobjekten anmelden.


Wie wird das denn richtig gemacht?


Edit: hm beim erstellen geht das ja noch garnicht. da gibts ja die View noch nciht...

Muss ich da nachträglich übr alle Artikel iterieren (in der view) und die Listener anmelden?
 
Zuletzt bearbeitet:
wie melde ich denn sonst beim erstellen des Artikels die View/ irgendeinen Controllr beim Artikel an?

Mein Disponenten Model hält listen aus Artikel, Rechnung, etc.,...

mein Controller greift auf di DB zu und erstellt diese Disponenten Model.

meine View bekomt controller und Model übergeben.--> View meldet sich beim Model als Listener an. (achtung hier meldet er sich nur für Änderungen an den Listen an) und das geht ja einfach so initial mit ein mal anmelden.

mein Model macht zb irgendwann mal...

setListData(model.getArtikelListe().toArray);

jetzt müsste das MOdel noch mtibekommen wenn sich artikel details ändern...also das Model am Artikel anmelden...Das ist jetzt die Frage wie das geht...So wie ich das oben geschrieben habe ist es ja im moment noch nciht.das wäre nur meine idee...also den Controller eine Referenz uf di View halten lassen (mit INterface PropertyChangeListener ( den müssen ja alles views die es dazu gibt haben)) und beim Model füllen einfach nru die referenzder View als Listener bei einzelnen Artikelobjekten anmelden.


Wie wird das denn richtig gemacht?

Check noch nicht was du mir genau sagen willst...
Ein Beobachter (View) bekommt ein ADD_ARTIKEL Event, anschließend macht die View irgendwas mit dem neuen Artikel oder ArtikelListe!!! Wenn die View jetzt irgendwas mit dem Artikel machen will z.b. beobachten kannst du doch hier deinen Listener hinzufügen...

btw: Du solltest auch nicht vergessen die Listener irgendwann mal wieder zu entfernen...
 
gut also iteriere ich nach dem erstellen der View (wo das Model ja schon steht) über alle meine Listen und füge die View als Listener an die (jeden einzelnen) Artikel z.b...

Das ADD_Artikel event kann ja erst ankommen wenn view am Model angemeldet ist und Model erst danach gefüllt wird.

PS: Die Listener müsste ich ja entweder beim löschen eines Artikels bzw beim beenden des Programms entfernen richtig!?
 
gut also iteriere ich nach dem erstellen der View (wo das Model ja schon steht) über alle meine Listen und füge die View als Listener an die (jeden einzelnen) Artikel z.b...

Das ADD_Artikel event kann ja erst ankommen wenn view am Model angemeldet ist und Model erst danach gefüllt wird.

PS: Die Listener müsste ich ja entweder beim löschen eines Artikels bzw beim beenden des Programms entfernen richtig!?

Bei Beenden ist es egal 😉, da kommt eh alles weg.

Dazu kann ich nichts sagen weil ich nicht weiß wie du deine Models usw. erstellst und wer alles die Artikel beobachten soll. Es gibt mehrer Möglichkeiten:

-Model mit Artikel Liste erstellen
-Controller erstellen
- View erstellen und Listener hinzufügen
- Model initialisieren oder initArtikels
--> View reagiert darauf...


Ja beim Löschen eines Models oder wenn sich eine View schließt o.ä.
 
ok ich mache es nun so in der "main" methode:

Java:
DisponentModel model = new DisponentModel ();
Controller conroller = new Controller(model, dbVerbindung);
View view = new View(model, controller);

Jetzt frage ich mich nur wie ich anschiebe dass ich danach das Modell füllen will. Mache ich dass immernoch in der main Methode dann?

so etwa:
Java:
controller.fillModel();

Oder gibt es da eine andere Vorgehensweise?
 
Zuletzt bearbeitet:
ok ich mache es nun so in der "main" methode:

Java:
DisponentModel model = new DisponentModel ();
Controller conroller = new Controller(model, dbVerbindung);
View view = new View(model, controller);

Jetzt frage ich mich nur wie ich anschiebe dass ich danach das Modell füllen will. Mache ich dass immernoch in der main Methode dann?

so etwa:
Java:
controller.fillModel();

Oder gibt es da eine andere Vorgehensweise?

Ja sowas in die Richtung fillModels initModels o.ä.
 
nochmal ich.. du hast oben geschrieben:
Java:
public void setId(Integer id) {
        changeSupport.firePropertyChange("id", this.id = id, id);
    }

bist du dir sicher dass dann ebi Listenern das propertyCHAnge ankommt? bei mir funktioniert es so nciht...dafür wenn ich es so mache :

Java:
public void setId(Integer id) {
int old = this.id;
this.id = id;

        changeSupport.firePropertyChange("id", old, this.id);
    }

So finde ich das aber irgendwie nicht so doll ... geht das bei dir denn nach der 1. methode? ist ja irgendwie komisch..
 
nochmal ich.. du hast oben geschrieben:
Java:
public void setId(Integer id) {
        changeSupport.firePropertyChange("id", this.id = id, id);
    }

bist du dir sicher dass dann ebi Listenern das propertyCHAnge ankommt? bei mir funktioniert es so nciht...dafür wenn ich es so mache :

Java:
public void setId(Integer id) {
int old = this.id;
this.id = id;

        changeSupport.firePropertyChange("id", old, this.id);
    }

So finde ich das aber irgendwie nicht so doll ... geht das bei dir denn nach der 1. methode? ist ja irgendwie komisch..

Sry fehler von mir falsch, so müsste es passen
Code:
changeSupport.firePropertyChange("id", this.id , this.id = id);

Aber variante 2 geht auch machen die meisten so, weils übersichtlicher ist.
 
Hallo nochmal.
Hätte nochmal eine Frage: Und zwar sieht in meiner View die Property Change methode so aus.
Java:
	@Override
	public void propertyChange(final PropertyChangeEvent evt) {
//		SwingUtilities.invokeLater(new Runnable() {
//			@Override
//			public void run() {
				

				String propName = evt.getPropertyName();
				if (propName.equals("AddBilling")) {
					getBillingList().setListData(
							model.getBillingList().values().toArray());
				}  else if (propName.equals("AddHistoryEntry")) {
					getLagerActivityList().setListData(
							model.getHistoryList().values().toArray());
				} else if (propName.equals("AddWorkItem")
						|| propName.equals("RemoveWorkItem")) {
                                        getTodoList().setListData(model.getWorkItemsList().toArray());
				}
//			}
//		});
	}
Man beachte das auskommentierte. Führe ich die ganze Sache nun ohne das invokeLater aus kommt es manchmal dazu dass einige Listen leer sind und erst mit dem nächsten geänderten wert wieder angezeigt werden, manchmal allerdings auch 20 mal nacheinander alles korrekt funktioniert.
Benutze ich an der Stelle das invokeLater (habe leider nur kurz zeit gehabt darüber zu lesen, aber es scheint wohl der synchronität des EDT und anderen Threads beizutragen (auch wenn ich nie explizit welche anlege!?), dann kommt es bisher zumindest nie vor das irgendetwas leer ist. Kann das damit zusammenhängen oder ist das zufall? Kann jemand was genaues zum invokeLater an dieser Stelle sagen? (Eig sollte das ja total sinnlos sein weil das PropertyChange event ja schon im EDT ausgeführt werden sollte ne?)

PS: Nebenbei gesagt benutze ich das invokeLater momentan nicht beim erstellen meiner GUI in der Main methode. hat / hatte das irgendwelche auswirkungen?
 
Zuletzt bearbeitet:

Zurück
Oben