Swing Java Applikation in MVC gut strukturieren

Michoel

Aktives Mitglied
Hallo Forum,
bin Student und wir sollen demnächst eine Java Swing Applikation schreiben mit einem Loginbereich mit drei verschiedenen Rollen/Rechten. Der mit den höchsten Rechten soll neue User und neue Briefings mit mehreren Zeilen anlegen können. Ich lade dann jede Zeile für ein Briefing das in der DB angelegt ist in ein BriefingObjekt und das für mehrere in eine ArrayList oder VectorContainer.
Der mit den mittleren Rechten kann die Briefings bearbeiten, der mit den niedrigen lesen. Und evtl. die Briefings ergänzen.

Habe jetzt die Tage ein paar Patterns gelernt. Das das nun mein erstes Java Projekt überhaupt im Leben ist und ich eine sinnvolle Aufteilung der Klassen erreichen will, wollte ich Euch nach Ratschlägen fragen, wie man dies am besten realisieren könnte? (Ich habe mir zwar auch MVC mit Model, View und Controller angeschaut, an der Umsetzung wird er sicherlich noch im ersten Projekt scheitern)


1. Ich mache eine Klasse connect_db für die Datenbankverbindung (JDBC)
2. Ein Interface CreateUserDAO, welches dann die konkrete Methoden vorschreibt, um einen User in die DB zu speichern, auszulesen, indem er die Klasse connect_db nutzt (Model / Logik ?)
3. Eine Klasse CreateUserDAO_db welches das Interface CreateUserDAO implementiert und die Methoden umsetzt. (Model / Logik ?)
4. Ein Interface CreateBriefingsDAO, welche die konkreten Methoden vorschreibt, um neue Briefings in die DB zu speicher, auszulesen, indem er die Klasse connect_db nutzt.
4. Eine Klasse CreateBriefingsDAO_db, welches das Inteface CreateBriefingsDAO implementiert und die Methoden umsetzt.

Da nun die die bestimmten Rollen ins Spiel kommt, da nicht jeder Briefings anlegen darf und später editieren darf, aber manche nur lesen, wenn die zugewiesen wurden für ein Briefing, frage ich mich nun, wie ich vorgehen soll.

Eine Klasse "start" wird dann später die Applikation starten, indem in der main-Methode die Loginmaske gestartet wird, indem ein Objekt view von der LoginmaskeGUI erstellt wird.
Jetzt habert es bei mir mega, wie ich da sinnvoll vorgehe?

Hätte jemand Tipps oder für mich einen kleinen Leitfaden, stehe irgendwie auf dem Schlauch.

Eine schöne Woche euch noch allen
Grüße
Lee
 
Jetzt hapert es bei mir mega, wie ich da sinnvoll vorgehe?
Ich verstehe nicht wirklich, was dein Problem ist. Generell enthalten Model Klassen die Daten und ihre Logik. Die von dir aufgezählten Klassen 1 bis 5 sehe ich entweder auf der Model Ebene oder eine Ebene darunter (da es ja dort eigentlich nicht um die logischen Daten als solche geht, sondern vielmehr um deren physischen Sicherung). Ein UserModel könnte die Login Daten aufnehmen, einschließlich der Benutzerrechte. In unseren FAQ findest du auch noch Infos zu "Model, View, Controller".
Good luck 🙂
 
Ich hoffe doch schwer, dass die dann nicht wirklich so heißt.
das war nur exemplarisch



Ich verstehe nicht wirklich, was dein Problem ist. Generell enthalten Model Klassen die Daten und ihre Logik. Die von dir aufgezählten Klassen 1 bis 5 sehe ich entweder auf der Model Ebene oder eine Ebene darunter (da es ja dort eigentlich nicht um die logischen Daten als solche geht, sondern vielmehr um deren physischen Sicherung). Ein UserModel könnte die Login Daten aufnehmen, einschließlich der Benutzerrechte. In unseren FAQ findest du auch noch Infos zu "Model, View, Controller".
hey danke andre, ich schaue heute in die FAQ's mal rein.


da das überhaupt mein erster Ansatz ist mit patterns und überhaupt GUI-Oberflächen, fehlt mir eben die Erfahrung und der Ansatz/Anfang.

Ich gehe evtl. folgend vor:

Eine main-klasse die etwa folgendes aufruft/erstellt:

UserModel userm = new UserModel()
Loginmaske loginview = new Loginmaske(userm)
LoginController lcontroller = new LoginController(userm, loginview)

Im UserModel empfange ich Userdaten und vergleiche in der Datenbank ob die Daten passen und lade evtl. bestimmte Daten von der DB.
Die Loginmaske erstellt die Maske und kennt das Usermodel und bietet Methoden um die Loginmaske zu bedienen/reseten oder Fehlermeldungen anzuzeigen

Der Controller kennt beide Objekte und es wird von dem Controller aus ein Listener auf das Loginbutton angelegt. (Wenn man nun auf das Loginbutton klicken würde, läuft es über den Controller. Nennt man so etwas "beim LoginController angemeldet/registriert"?)


Der Controller managed nun die Interaktionen untereinander, also das aufrufen der Methode des UserModels von der View. Also wenn auf das Loginbutton gedrückt wird, wird die Methode usercheck aufgerufen. Nun kann die Methode ein ok zurückliefern oder ein false, oder bei ok auch gleich die userdaten/infos zurückgeben.

Wie verhalte ich mich nun im controller am besten? Wenn ein ok zurückkam, dann soll der controller einen persönlichen bereich laden in das gleiche fenster oder ein neues controller ansprechen(hier hängt es noch einwenig, wie er es laden muss usw.)

Ich versuche weiter zu verstehen. Wenn nun auch persönlicher Bereich, persönliche Maske angezeigt/geladen wird, wie das auch immer geschieht,dann erstelle ich vom Prinzip her die persönliche Maske wie in etwa im oberen Bereich:


Usercheck/UserModel userm = new UserModel()
Personalmaske personalview = new Personalmaske(userm)
PersonalController pcontroller = new PersonalController( userm, personalview)

Der PersonalController, bzw. der obere Controller lädt die Personalmaske. Er muss sie aber so laden, wie nach den Rechten passt. Hmmm, da muss ich überlegen kurz.
Der obere LoginController hat ja ein ok zurückbekommen dann hat er entweder auch paar Userdaten zurückbekommen, u.a. die Rechte und dann lädt er entweder je nachdem zwei verschiedene Personalviews je nach Rechten oder er übergibt einer einzigen View die Rechte und die View erstellt dann mit eine IF-abfrage dementsprechend die Ansicht.

Ist das letztere so in Ordnung?
wenn ich das verstanden habe, sollte ich den Rest dann auch hinkriegen denke ich, so ganz dumm sollte ich nicht sein hoffentlich 🙁
 
so ganz dumm sollte ich nicht sein hoffentlich
Deine Ausführungen sind schon nicht so dumm, also Kopf hoch, das schaffst Du schon 🙂

Die View wird gewöhnlich beim Model als Listener/Observer registriert. So kann sie auf Änderungen im Model reagieren. Sie kennt den Controller, um die Benutzeraktionen an ihn weiterzugeben. Ob der Actionlistener (z.B. eines Buttons) in der View oder im Controller liegt, ist von untergeordneter Bedeutung. Die Benutzeraktionen müssen lediglich irgendwie beim Controller landen.

Der Controller ist hauptsächlich ein Übersetzer: er verwandelt die Benutzeraktionen (z.B. den Klick auf "OK") in Aktionen, die das Model ausführen soll. Der Controller kennt also das Model: er sagt ihm was zu tun ist, aber er ist nicht unbedingt an Feedback interessiert.

Das Model kennt weder die View noch den Controller. Es macht einfach das, was der Controller ihm sagt und gibt Rückmeldung an alle registrierten Listener/Observer, d.h. normalerweise an die View(s).

Code:
UserModel userm = new UserModel()
LoginController lcontroller = new LoginController(userm)
Loginmaske loginview = new Loginmaske(lcontroller)
userm.addUserModelListener(loginview)

Code:
PersonalModel personalm = new PersonalModel(userm)
PersonalController pcontroller = new PersonalController(personalm)
Personalmaske personalview = new Personalmaske(pcontroller)
personalm.addPersonalModelListener(personalview)

Ich hoffe, Dir damit geholfen zu haben.

EDIT: Die korrekte Initialisierung der Personalmaske könnte so aussehen:
Code:
pcontroller.init() -> personalm.init() -> Feedback an PersonalModelListener (=Personalmaske)
 
Zuletzt bearbeitet:
Hey Andre,
vielen Dank für deine Bemühungen. Ich versuche mein bestes zu geben und versuche auch nicht in Foren herumzuschnorren, sondern zu verstehen. So langsam bildet sich aber das Gebilde.

A) Dein Vorschlag hört sich sehr gut an. Ich weiß wie es funktioniert, wenn ein Objekt ein anderes kennt. Das heißt dann im Prinzip dass beim Konstruktor oder mittels Methoden das Objekt des zu kennenden Objekts übergeben wird. Ich frage mich nun,wie es aussieht, wenn man nicht ein Objekt kennt, sondern registrierte Listener hat?

Das Model kennt weder die View noch den Controller. Es macht einfach das, was der Controller ihm sagt und gibt Rückmeldung an alle registrierten Listener/Observer, d.h. normalerweise an die View(s).

Code:
1. UserModel userm = new UserModel() //Model kennt niemand, Programmierer kann das alleine entwickelt und Model flexibel überall einsetzen
2. LoginController lcontroller = new LoginController(userm) //Controller kennt Model um Interaktionen anzustoßen
3. Loginmaske loginview = new Loginmaske(lcontroller) //Die View benachrichtigt den Controller über Änderungen, damit Controller neue Interaktionen übermitteln kann
4. userm.addUserModelListener(loginview) //Das muss ich mir dann anschauen, wie registrierte Objekte allgemein aussehen, sei es im GUI-Bereich oder Web-Bereich.


Code:
1. PersonalModel personalm = new PersonalModel(userm) //Dem anderen Model wir das andere Model auch bekannt macht, bzw. beide arbeiten zusammen / bzw. auf dem Objekt wird weitergearbeitet. Da sollte ich mir eventuell Interfaces anschauen, wenn man das Model flexibler/unabhängiger gestalten will.
2. PersonalController pcontroller = new PersonalController(personalm) /Der Rest ist wieder wie ob, so dass ich nur das "Registrieren" im allgemein verstehen muss.
3. Personalmaske personalview = new Personalmaske(pcontroller)
4. personalm.addPersonalModelListener(personalview)



Ich hätte dann noch paar andere Kleinigkeiten zum Prinzip bzw. Aufbau, dann könnte ich eigentlich schon mal loslesgen mit dem Programmieren.




B) Der Kontroller könnte ja dann ein UserModel aufrufen, welches dafür zuständig ist ein Datenbankobjekt anzulegen, damit die Vebrindung steht ne. Daran ist nichts auszusetzen? Wobei, das hat ja das erste Model schon gemacht, als es überprüfte ob die Logindaten stimmen, dazu hatte das Model ja ein anderen Model aufgerufen. Oki, dann wäre das auch geklärt.

C) Das UserModel hat ja ein UserObjekt angelegt. In den folgenden Seiten, wenn man sich immer weiter reinlickt, bzw. Personalmaske und den folgenden Seiten muss ich immer prüfen, ob der User eingeloggt ist bzw. das UserObjekt besteht. Wo würde ich diese Überprüfungen für jede Maske dann immer korrekt machen, wenn ich zum Beispiel die Personalmaske lade, und später zum Beispiel, wenn man die Maske aufruft, um ein neues Briefing anzulegen. Wenn ich da noch das Zusammenspiel habe, wäre ich vermutlich in der richtigen Richtung. (Irgendwann kille ich das UserObjekt bzw. setze es auf NULL und werde automatisch in die Loginsmaske weitergeleitet)

Ich bedanke mich nochmals bei dir Andre und danke dass du mir auch Mut machst 😉
Grüße
M.
 
A): Die Verwaltung der Event Listener wird hier erklärt: EventListenerList (Java Platform SE 6)

B): Ich verstehe nicht wirklich, was du hier meinst, aber da am Schluss steht "Oki, dann wäre das auch geklärt", muss ich das ja wohl nicht.

C): Wenn wir so was machen:
Code:
PersonalModel personalm = new PersonalModel(userm)
dann kennt das PersonalModel ja auch das UserModel. Es kann somit problemlos die Benutzerrechte überprüfen und der Personalmaske (als PersonalModelListener) entsprechend Rückmeldung geben.
 
Hi Andre,
vielen vielen Dank. Ich fange mal jetzt gleich an zum proggen und hoffe, dass ich keinerlei fragen haben. (Vielleicht hättet ihr nichts dagegen, wenn ich hier unterrichte, wie ich anfange, bzw. was ich mache) Wenn es nicht sinnvoll oder ein schlechter Stil ist, könnte jemand dazu ein Kommentar abgeben? :bahnhof:

Ich fange jetzt mal an, unabhägig eine Klasse (Model) "database_con" zu erstellen, die die Verbindung speziell für die Datenbank mysql aufbaut.
Dann kommt eine Klasse (Model), die Objekte User, Briefings, Umfrageformular empfängt und in die DB-Speichert mit er Klasse "database_con" oder auch die Objekte auslesen kann. Evtl. überlege ich mir, ob ich für jeden Punkt User, Briefings usw. ein eigenes Model schreib, das ein Objekt von dem Typ empfangen und in die DB schreiben bzw. auslesen kann.

Wenn ich fertig bin, geht es dann weiter 😉
 
Hallo Forum,
mit der DB-Klasse nicht arg vorangekommen, das ganze dürfte aber nicht schwer sein.
Habe jetzt eine DB-Klasse mit einem Konstruktor, getConnect und disconnect, dann kommen noch zwei Methoden, um eine SQL-Anweisung reinzuschicken (Update/Alter) und eine SQL-Anfrage um ein Ergebnis zurückzubekommen (Rückgabetyp muss ich mir dann noch überlegen, so dass ich das gut vearbeiten kann)
Eventuell kommen aber die zwei letzten Methode in eine separate Klasse, die SQL-Anfragen entgegennimmt.


Jetzt mache ich mir Gedanken, wie ich das erste mal die erste GUI-Oberfläche anzeige.
Eine Start-Klasse hat die einzige main-Methode die dann ein Model, View und Controller startet oder ich starte nur direkt einen Controller mit new Controller();
Der Controller hätte dann eine JFrame (Loginmaske) Membervariable, der dann die Loginmaske startet.


1. In der Loginmaske werden nun die Logindaten eingeben, welche dann an die Klasse übermittelt werden, die den Listener implementiert.
Nun frage ich mich, ob ich später für jede Komponente in verschiedenen GUI-Maske einen Listener programmieren soll/muss, der dann irgendwie auf Klicks oder irgendwelche Sachen reagiert.
Hier in diesem Beispiel sind zwei innere Klassen in den Controller integriert, die auf Klicks reagieren:
Java: Model-View-Controller (MVC) Structure
Aber, man kann ja nicht den Controller so voll fluten.

In dem Thread jedoch wollten wir ja etwas anders vorgehen als das MVC-Beispiel oben, nämlich wie folgt:
UserModel userm = new UserModel()
LoginController lcontroller = new LoginController(userm)
Loginmaske loginview = new Loginmaske(lcontroller)
userm.addUserModelListener(loginview)

Sobald wir ein Exemplar von Loginmaske erstellen, wird die GUI angezeigt (Sichtbar gemacht) und die Maske kennt den Controller.
Jetzt passiert dort eine eingabe und es wird der Actionlistener aufgerufen (der am besten irgendwo Zentral für die ganze Applikation liegen sollte). Dort wird dann zum Beispiel im Controller die Methode logincheck aufgerufen. Der Controller wiederum ruft nun ein Model auf, übergibt noch die Daten dem Model. Das Model prüft in der Datenbank, falls alles passt, wird ein UserObjekt angelegt.
Jetzt muss eine neue GUI erstellt werden, wie gehe ich da am besten vor? Leider habe ich halt das letzte "userm.addUserModelListener(loginview)" nicht ganz verstanden, wie ich das gestalten würde, dass das Model dann die Loginmaske anstößt irgendwie. Das Problem ist ja, falls die Eingabedaten falsch sind, soll in der Loginview ein kleiner Text erscheinen, dass die Anmeldung falsch war, ansonsten wird eine neue GUI angezeigt mit dem persönlichen Bereich des Users. Könnte man hier pauschal Tipps geben oder wäre das zu aufwendig?


2. Später, wenn man im persönlichen Bereich ist hat man ja ein Menübar, irgendwelche Icons drin, um neue Benutzer anzulegen (Je nach Benutzerrolle) oder neue Briefings anzulegen usw.
Nun frage ich mich, ob ich für jede GUI bzw. Maske dann immer das obere Menübar oder Icons immer neue einfügen muss? Heute stehe ich nur auf dem Schlauch 😉
(Bsp in Masken oben ein Menübar mit dem Menü "Datei" und dem MenüItem "Exit" oder "Info". Pro Maske ein ActionListener immer aufs Neue wäre nicht sinnvoll.

Grüße
 
Zuletzt bearbeitet:
Das Wesentliche am Controller sind nicht die Listener selbst. Wichtig ist nur, dass die Benutzeraktionen beim zuständigen Controller ankommen und dort in Modelaktionen übersetzt werden. Wie und wo die Listener umgesetzt werden, ist für den Controller eigentlich unwichtig.

Das Wesentliche an einer View sind auch nicht die Bedienungselemente selbst. U.u. können mehrere Views sich einige der Bedienungselemente teilen. Wichtig ist nur, dass diese in der Lage sind, die Benutzeraktionen an den zuständigen Controller weiterzuleiten.

Als UserModelListener hat die Loginmaske eine Methode wie z.B. "userModelChanged(UserModelEvent e)", die vom UserModel aufgerufen wird. Die Loginmaske muss dann das Event auswerten, um zu entscheiden, ob ein kleiner Text erscheinen soll, dass die Anmeldung falsch war, oder ob eine neue GUI angezeigt wird mit dem persönlichen Bereich des Users.
 
Hi Andre, okey vielen vielen Dank. Die ersten beiden Passagen sind dann mir klar, außer das letzte noch, mit dem UserEvent. Irgendwie eiere ich da übelst herum. Vielleicht liegt es auch nur an der Uhrzeit.



Als UserModelListener hat die Loginmaske eine Methode wie z.B. "userModelChanged(UserModelEvent e)", die vom UserModel aufgerufen wird. Die Loginmaske muss dann das Event auswerten, um zu entscheiden, ob ein kleiner Text erscheinen soll, dass die Anmeldung falsch war, oder ob eine neue GUI angezeigt wird mit dem persönlichen Bereich des Users.

userm.addUserModelListener(loginview)


Ich schaue mir das dann morgen nochmal in aller Ruhe an und hoffe, dass ich das dann noch verstehe, dann dürfte ich mit den GUI's und Models anfangen können :rtfm:

gute nacht euch allen
:gaen:
 
Ich überlege mir einige Einstellungen aus einer Textdatei bzw. properties Datei auszulesen bzw. auch Texte auf einer language Datei.

Für den Webbereich hab ich eine PropertiesReader für Einstellungen auslesen und für Sprachdateien eine MessageResource welches mit "ResourceBundle messages = ResourceBundle.getBundle(MESSAGE_RESOURCE, locale);" hantiert. Kann man das im GUI-Bereich auch einsetzen? Muss dazu ja nur ein locale bilden und mit Icons später hin und her switchen.

Mit was könnte ich allgemein die Scripte loggen, falls da Fehler passieren?
Im Webbereich hatte ich folgendes im Einsatz:

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

if(log.isDebugEnabled()) log.debug("Meine Meldung");

dazu gab es dann noch 3 Einstellungsdateien (commons-logging.properties, log4j.properties und log4j.xml)

Grüße
 
Also die Sprachdatei geht eigentlich fast.

Ich habe eine Klasse "LangRes" angelegt mit der Instanzvariable:

public static final String language_res= "language";

eine language.properties liegt dann im netbeans ordner. (In keinem Paket)


Dann bilde ich in irgend einem Script das Objekt (später im Controller)

LangRes getLanguageText = new LangRes();
Dann führe ich die Methode aus, die die Variable in der proprties Datei ausliest:

System.out.println("Sprachtest "+getLanguageText.getMessage("variable", Locale.ENGLISH));

Dann holt er automatisch die variable von der language.properties. Nun dachte, sobald ich im Methodenaufruf das Locale.ENGLISH in Locale.GERMAN ändere, dass er automatisch die language.properties um ein ger oder ge ergänzt. also language_ger.properties. Er sucht aber dennoch die language.properties.

Muss ich das auch noch speziell, bzw. manuell reinprogrammieren in die Klasse "LangRes", dass sobald die Locale.German kommt, dass er anstatt language.properties eine deutsche language_ger.properties holt? (Also die Instanzvariable dann ändern?)

Grüße
 
Das mit den languages klappt nun auch.


Was noch nicht geht. Ich habe mit Netbeans eine Maske "Mask" erstellt.

Der Controller hat nun eine Instanzvariable von der "Mask" und ein Listener was actionListener implementiert. Beim initialisieren im Controller der Mask firstimask=new Mask(this) gibt der Controller sich selber mit this mit.


In der Loginmask füge ich nun einem JButton1 einen addActionListener in etwa wie folgt:

jButton1.addActionListener(cont.getListener()); (da der Controller ja den Listener kennt und den Listener als Instanzvariable hat)
jButton1.setActionCommand("login");

Bei einer Aktion wird nun der actionPerfomed vom Listener aufgerufen. Der Listener ruft nun in der Methode eine Methode namens loadUser vom Controller auf, da der Controller nun entscheiden soll, was passiert.


Nun bin ich in der Methode loadUser des Controller, von dort aus ich ein UserModel aufrufen will, der mit dann einen User lädt falls er vorhanden ist, ansonsten NULL zurückgibt, falls es keinen User gibt.


1. Mein Problem nun. Eigentlich kennt doch der Controller die Mask. Ich müsste doch eigentlich vom Controller heraus die Textfelder für Username und Passwort auslesen müssen oder muss man da explizit getterMethoden für die zwei Textfelder in Mask schreiben?


2. Ich könnte doch sicherlich zum Beispiel allgemein das jMenü eines GUIS oben in einer extra Klasse (TopMenu) programmieren, welches nur für ein Menü zuständig ist. Und dann beim Controller der Mask irgendwie zuweisen ne? (Oder die Mask holt sich das von der Klasse TopMenu die öbere Menüleiste mit Inhalt?
Wie geht man da am besten vor?

Würde mich über Tipps sehr freuen. Damit der Thread nicht so voll aussieht, lösche ich oben mal die erledigten Sachen.


P.S.
(Komisch finde ich, dass ich im Paket wo sich die Masken befinden das Paket vom Controller direkt angeben muss. Also packetname.* reicht nicht, sondern packetname.Controller)
 
Zuletzt bearbeitet:
Hoffentlich habe ich kein SPAM gemacht und einen schlechten Eindruck hinterlassen, da niemand mehr antwortet 🙁

Ich bemühe mich aber wirklich
 

Neue Themen


Zurück
Oben