Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Do Jul 10, 2025 21:09

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 14 Beiträge ] 
Autor Nachricht
BeitragVerfasst: So Sep 13, 2009 13:46 
Offline
Guitar Hero
Benutzeravatar

Registriert: Do Sep 25, 2003 15:56
Beiträge: 7810
Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
So, ich grübel über ein Problem, welches eigentlich schon mehrfach gelöst worden sein dürfte.
Ich hoffe also auf ein paar Tipps, quasi "Best Practices" von euch.

Es geht darum, dass ich an die Engine meines PBall Managers zwei GUIs anbinden möchte.
Die Idee dahinter ist, dass ich für die Entwicklung der Engine eine sog. "Developer GUI" baue mit der ich die Funktionalität ausprobieren kann,
und dann später für die Endanwender diese DevGUI durch eine richtige OpenGL GUI ausgetauscht wird.

Man kennt ja das Modell-View-Controller Prinzip. Eigentlich also alles Standard.

Der Ablauf soll so sein:

1. Meine Engine wird gestartet.
2. Die Hauptklasse erwartet einen GUI Controler um mit der GUI zu reden. (GUI Controler = Interface)
3. Die Engine startet das GUI Modul mittels einer GUI Controler Implementation die z.B. mittels Reflection geladen wurde.
4. Der GUI Controler erstellt das Fenster
5. Der GUI Controler greift auf eine GUI-Modell-Factory (aus dem Engine Package) zurück, wenn ein neues Menü geöffnet werden muss.
Für jedes Menü muss ein GUI Modell (Datenmodell) verfügbar sein. Der GUI Controller verknüpft dann die GUI mit ihrem Modell.
Diese GUI Modelle werden genutzt, wenn die GUI Daten an die Engine übergeben will bzw. wenn Funktionen (BusinessLogic) in der Engine ausgeführt werden müssen.

Soweit so gut.
Im GUI Controller ist der Maskenfluss programmiert. Also welche Maske von welcher aus geöffnet wird usw. Das hat den Vorteil, dass man den Maskenfluss nur an dieser Stelle warten muss und nicht sonstwo reingreifen muss.

Wo ich gerade hänge ist der Fall von "Rückfragen" bzw. "Dialogen".

Also folgendes Szenario:

Der User Clickt auf einen Button.
Die Maske weiß: "Bei Click auf diesen Button rufe die Funktion "handleBtnClick" im Maskenmodell auf.
Die Maskenmodell Klasse weiß, ich muss jetzt in der Engine die Funktion "tueIrgendwas()" aufrufen.
In dieser Funktion tritt jetzt ein Fehler auf, oder es muss eine Rückfrage an den User gestellt werden.

Wie soll das gehen? Und vor Allem, wie soll die Antwort des Dialogs in die Funktion eingeschleußt werden?

Habt ihr Ideen? Wie habt ihr eure GUI von euren Kernfunktionen getrennt?

_________________
Blog: kevin-fleischer.de und fbaingermany.com


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Sep 13, 2009 14:45 
Offline
DGL Member
Benutzeravatar

Registriert: Di Dez 27, 2005 12:44
Beiträge: 393
Wohnort: Berlin
Programmiersprache: Java, C++, Groovy
Hallo Flash,

hört sich so an als würde deine Maskenmodell Klasse eine Controller-Rolle übernehmen.
'handleBtnClick' sollte von einem Controller aufgerufen werden, der dann wiederum entscheidet, was mit der Maskenmodell-Klasse passiert.
Wenn ein Fehler auftritt, sollte der Controller Rückfragen an den User stellen.
Ist nur die Frage ob du das in dem Gui-Controller machst oder einen eigenen Controller ( z.B. einen Action-Controller ) dafür verwendest.

Viele Grüße
dj3hut1


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Sep 13, 2009 15:09 
Offline
Guitar Hero
Benutzeravatar

Registriert: Do Sep 25, 2003 15:56
Beiträge: 7810
Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Ok...

Dein Vorschlag hat mich nochmal drüber nachdenken lassen.

Es gibt prinzipiell nur zwei Arten von solchen "Out-Of-Order" Fenstern.

1. Fehlermeldungen

2. vorhersehbare Dialoge (z.B: "Soll Spielstand überschrieben werden?")

Erster Fall ist einfach.
Die GUI-Modell-Klasse sagt dem GUI Controller, dass er einen Dialog mit dem Inhalt ABC anzeigen soll.

Der Zweite Fall ist komplizierter.
Die GUI-Modell Klasse prüft ob ein Dialog angezeigt werden soll und beauftragt den GUI Controller entsprechend.
Das der GUI Controller den Dialog anzeigt ist nix besonderes, schließlich ist das vergleichbar mit einem normalen "Zeige Maske an" aufruf.
Allerdings ist jetzt die Frage, wie es weiter geht.
Wenn der Dialog sichtbar ist, wie bekomme ich die Antwort, auf welchen Button geklickt wurde zurück an mein ursprüngliches Dialogmodell...? Damit der Dialog angezeigt wird, muss doch die GUI insgesamt mind. 1mal neu gezeichnet werden. Wir hängen aber immer noch im Handler.

Oder habe ich hier einen Denkfehler?

_________________
Blog: kevin-fleischer.de und fbaingermany.com


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Sep 13, 2009 16:59 
Offline
DGL Member
Benutzeravatar

Registriert: Di Dez 27, 2005 12:44
Beiträge: 393
Wohnort: Berlin
Programmiersprache: Java, C++, Groovy
Hallo,

wenn ich das richtig verstanden habe, steuerst du mit deiner GUI-Modell-Klasse den GUI Controller, aber sollte es nicht eigentlich andersherum sein?

Ich hatte es mir so vorgestellt :

1. GUI wird angezeigt
2. User löst eine Aktion aus, z.B. Drücken eines Buttons
3. Ein Controller, z.B. der GUI Controller ( oder ein zusätzlicher Action-Controller ) wird als Handler aufgerufen
4. Dieser füllt nun z.B. deine GUI Modellklasse mit Daten oder führt eine Funktion der Modellklasse aus, falls dort ein Fehler auftritt wird eine Exception geworfen
5. Der Controller fängt die Exception ab und ruft einen Dialog auf.
6. Der Dialog wird wieder vom Controller gehandelt usw.


Viele Grüße
dj3hut1


Zuletzt geändert von dj3hut1 am So Sep 13, 2009 17:27, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Sep 13, 2009 17:16 
Offline
DGL Member
Benutzeravatar

Registriert: Di Okt 03, 2006 14:07
Beiträge: 1277
Wohnort: Wien
Ich würde Dir ja gerne helfen, aber Du hast das total anders implementiert als ich. Ich habe z.B. gar keinen GUI-Controller, nur ein Objekt, das die Events herankarrt und es dem zuständigen Fenster übergibt. Die einzelnen Widgets sind ziemlich selbstständig:

Wenn ein Dialog angezeigt werden soll, so erfährt es das zuständige Item XY. Dieses Item hat einen Eventhandler dabei, der veranlasst, dass ein spezieller Dialog angezeigt wird. Jeder anklickbare Button des Dialogs hat einen Eventhandler eingebaut, der die nötigen Dinge in die Wege leitet. Der Button-Eventhandler kann z.B. mit dem Dialogfenster in Verbindung treten und dessen Eventhandler in Gang setzen. Dadurch ist ein Controller gar nicht nötig. Es ist gewissermassen eine Art "Kettenreaktion" und funktioniert wie eine instinktgesteuerte Handlung. Wenn die Eventhandler alle fertig sind, kommst Du automatisch wieder zum zuständigen Item XY zurück.

In Pascal sind die Eventhandler Callbackfunktionen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Sep 14, 2009 09:21 
Offline
DGL Member
Benutzeravatar

Registriert: Di Sep 03, 2002 15:08
Beiträge: 662
Wohnort: Hamburg
Programmiersprache: Java, C# (,PhP)
Eigentlich ist doch eher die Frage wie viel Aufwand du betreiben willst.

Damals bei UT gab es das UWindow System. Sehr mächtig und entsprechend komplex für den UnrealScript Programmierer. Wie es bei UT3 aussieht kann ich aktuell nicht sagen, hab das Spiel nicht...in UT2kx jedenfalls gab es ein System das ähnlich dem dir vorschwebenden ist.

Ein GUIManager der sich um alles kümmert und jede GUI Seite die man sieht entsprach einer GUIPage. Die kommunizierten mit dem GUIManager und lagen auf dessen Stack, der entsprechend für die Anzeige zuständig war.

Den Buttons konnte man Events zuweisen und diese haben dann in aller Regel eine neue Page aufgerufen. Wie groß die Page dabei war, war unerheblich, da sie auch nur einen Teilausschnitt des Bildschirmes nutzen durfte.

Leider bot das System nicht mehr die Vielfalt des UWindow Systems und war entsprechend unbeliebt bei der Modding Community.

Wie gesagt, aus meiner Sicht ist eher die Frage wie viel Aufwand du betreiben willst.

Achja, beim UT2kx System konnte man Ingame die Elemente verschieben/skalieren und sich dann per STRG+C die Positionswerte besorgen. Das war wirklich praktisch.

_________________
(\__/)
(='.'=)
(")_(")


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Sep 14, 2009 14:54 
Offline
Guitar Hero
Benutzeravatar

Registriert: Do Sep 25, 2003 15:56
Beiträge: 7810
Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Das Problem ist, dass GUI und Engine logisch getrennt sind. Was nicht möglich ist, ist dass Klassen aus beiden Packages sich direkt gegenseitig aufrufen. Das wäre eine Kreisabhängigkeit.

D.h. entweder die Kommunikation von GUI in die Engine ist einfach zu machen, oder die Gegenrichtung.

Aber wie bekomme ich es hin, dass ich in beide Richtungen kommunizieren kann?....

Vielleicht gibts ja ein passendes Pattern... :?:

_________________
Blog: kevin-fleischer.de und fbaingermany.com


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Sep 14, 2009 15:05 
Offline
DGL Member
Benutzeravatar

Registriert: Di Sep 03, 2002 15:08
Beiträge: 662
Wohnort: Hamburg
Programmiersprache: Java, C# (,PhP)
Wieso soll die GUI denn überhaupt mit der Engine kommunizieren? Die einzigen Schnittstellen die von der GUI nach benötigt werden sind die Möglichkeit eine Texture an ein GUI Element zu binden sowie Keys und eventuell noch Sound Effekte. Ansonsten sollte die GUI meiner Meinung nach möglichst autark funktionieren.

Oder andere Idee: Der GUIManager kann Dinge wie Texture/Sounds/Keys an die Engine weiterleiten/registrieren und ist somit das einzige Bindeglied. Getreu dem Motto "Hey Engine, ich hab hier was das ich nutzen möchte, hilf mir mal damit" ;)

_________________
(\__/)
(='.'=)
(")_(")


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Sep 14, 2009 17:37 
Offline
Guitar Hero
Benutzeravatar

Registriert: Do Sep 25, 2003 15:56
Beiträge: 7810
Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Das klingt alles sehr nett, aber das hab ich ja versucht umzusetzen.

Die GUI muss der Engine Eingaben vom Nutzer übermitteln.
Das können einfache Zahlen und Strings sein aber auch Aufrufe von Logic z.B. "setze den ausgewählten Spieler auf die Transferliste".

Die Engine muss mit dem User/GUI kommunizieren und zwar im Fehlerfall ("Es ist Fehler ABC12239 aufgetreten") und bei Rückfragen. Wobei letztere vielleicht sogar durch vorrausschauendes Handeln außerhalb der GUI abgearbeitet werden können.

Zumindest aber muss die Engine die GUI starten - oder doch nicht?

_________________
Blog: kevin-fleischer.de und fbaingermany.com


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Sep 14, 2009 18:24 
Offline
DGL Member
Benutzeravatar

Registriert: Di Okt 03, 2006 14:07
Beiträge: 1277
Wohnort: Wien
Flash hat geschrieben:
Aber wie bekomme ich es hin, dass ich in beide Richtungen kommunizieren kann?

Musst Du gar nicht, Du musst es nur intelligent zusammenspannen:


Angenommen, GUI und Engine sind getrennt: die Applikation liefert Maus- und Tasten-Events an die Engine weiter(wie auch immer). Die Engine hat dann ja ihrerseits wieder Events, z.B. das "Spielstand speichern"-Event. Da die Engine in diesem Fall keinen Zugriff auf die GUI hat, teilt sie der Applikation per Event mit, dass nunmehr das Speichern des Spielstandes ansteht. Der Eventhandler der Applikation wendet sich an die GUI und erzeugt einen "Speichern-Dialog", den der Benutzer abarbeitet. Wenn dieses Event zu Ende ist, fährt die Engine einfach fort, ihre Arbeit zu tun, denn das Event geht ja von der Engine aus, also kann die Engine auch nahtlos weitermachen.

Dazu muss die Engine Zugriff auf die Maus- und Tasten-Events haben, ein Event definiert haben, das von der Applikation abgehandelt wird und die Applikation braucht Zugriff auf die GUI. Events sind eine Art Nervensystem zwischen Applikation, GUI und Engine. Oder vielleicht so: die Applikation ist der Leim zwischen GUI und Engine.


Oder aber, die GUI und die Engine bilden eine Einheit, dann muss sich die Engine um alles selber kümmern, auch um die Programmhauptschleife. Im obigen Fall würde das so aussehen: Die Engine kommt zum Event "Spielstand speichern", ruft die GUI selbsttätig auf, wartet, bis der Benutzer mit seinem Dialog fertig ist, und macht wieder weiter.

Vorteil: die Applikation muss überhaupt nicht eingreifen.
Nachteil: wenn die Applikation trotzdem ihre Kontrolle beibehalten will, muss die Engine-API alle GUI-Befehle "durchschleusen", also so etwa:

"MyEngine.CreateWindow(Left,Top,Width,Height, BlaBla..)"

Und das muss man mit jedem GUI-Befehl machen, den die Engine ausführen können soll. Ziemlich viel Arbeit, puh. Und wenn sich die GUI ändert, muss man an der Engine-API rumpfuschen.



NACHTRAG: Das Fenster erzeugt der, der die Kontrolle drüber hat. Im Fall Eins die Applikation, im Fall Zwei die Engine.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Sep 14, 2009 19:20 
Offline
DGL Member
Benutzeravatar

Registriert: Di Sep 03, 2002 15:08
Beiträge: 662
Wohnort: Hamburg
Programmiersprache: Java, C# (,PhP)
Die Engine sollte keine Kenntnis von den Events haben. Besser wäre es das key/Mouse Event an die GUI zu reichen sofern sich selbige dafür interessiert und die GUI kann dann sagen - OK, ich hab hier nen ESC Event und breche den aktuellen Dialog ab.

_________________
(\__/)
(='.'=)
(")_(")


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Sep 14, 2009 21:14 
Offline
DGL Member
Benutzeravatar

Registriert: Di Okt 03, 2006 14:07
Beiträge: 1277
Wohnort: Wien
Zitat:
Die Engine sollte keine Kenntnis von den Events haben.

Ja, klar, Du hast recht. Ich hab vermutlich in meinem Eifer, das Zeug zu beschreiben, die Hälfte nicht erwähnt.
Also ganz genau heißt es:

Das Fenster (das ein Bestandteil der GUI ist) übermittelt den ESC-Key irgendwie an die Engine. Da Engine und GUI hier getrennt sind, muss es eine Art Überbringer geben. Es gibt jedenfalls KEINE direkte Leitung Betriebssystem an Engine, alles muss über ein Fenster laufen, sonst geht alles durcheinander wie Kraut und Rüben.

Sodann ruft die Engine ihr Event für diesen Fall auf und der Eventhandler ist ein Teil der Applikation. Die Applkation kann die GUI bedienen und kann daher einen entsprechenden Dialog aufrufen, der vom Benutzer zu bedienen ist.

Nach Klicken auf den jeweiligen Knopf übernimmt der Eventhandler des Knopfes und erledigt die Status-Speicherung.
Ende Eventhandler Knopf => Ende Eventhandler Applkation => Zurück an Engine. Womit die Engine wieder weiterarbeiten kann.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Sep 15, 2009 09:17 
Offline
Guitar Hero
Benutzeravatar

Registriert: Do Sep 25, 2003 15:56
Beiträge: 7810
Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Ich hab mich gestern abend mal hingesetzt und mir auch nochmal gedanken dazu gemacht.
Ich denke ich hab einen Weg gefunden.

Ich hatte bisher den Fehler gemacht zu glauben, dass weder GUI noch Engine direkt auf das jeweilige gegenüber zugreifen kann. Das ist aber zuviel des Guten. Die GUI (Controller) darf durchaus auf die Engine zugreifen und dort z.B. die GUI-Modell-Controler anfordern. Diese speichern die Werte der GUI, machen die Aufrufe der Businessfunktionen und teilen über Returncodes der GUI mit, wenn ein neues Fenster geöffnet werden soll.

Da die Modell-Controller in der Engine liegen, kann ich die eigentliche GUI austauschen. Die neue GUI erhält dann auch die Modell-Controller und muss dann nur noch entsprechend reagieren.

_________________
Blog: kevin-fleischer.de und fbaingermany.com


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Sep 15, 2009 13:00 
Offline
DGL Member
Benutzeravatar

Registriert: Di Mai 18, 2004 16:45
Beiträge: 2623
Wohnort: Berlin
Programmiersprache: Go, C/C++
Naja du brauchst zum einen Events und zum anderen ein Interface um dinge zu malen.
Früher hatte ich das so gelöst, dass ich eine große Klasse GUI hatte, dieser konnte man ein Canvas übergeben und hat BasisEvents(MouseMove,MBtnDown/Up,KeyDown,KeyUp,Resize) entgegen genommen und dann in diesem die Events zu komplexeren Events ausgearbeitet, wie z.B. Drag&Drop, MouseClick, KeyClick und so weiter. In einer Lösung hat dann die GUI alle obersten Fenster neue Events weiter gegeben und ging dann rekursiv durch. Später bin ich auf EventListen umgestiegen, wo sich jede Komponente für ein Spezielles Event in der Liste von GUI gemeldet hat(rekusion fällt weg und es werden weniger Objekte angefasst und weniger Funktionscalls ausgeführt). Heute hab ich diese Superklasse gekillt, nun klemmen alle Komponenten am Fenster, welches ja sowieso alle Events hat und auch ein Canvas/Context besitzt. Also hat jedes Widget ein Pointer auf ein IWindow(Fenster für Canvas, Drag&Drop Objekt und so weiter) und IControl(Parent) und Events werden direkt am IWindow gehangen.
So ruft das Fenster-Objekt die Liste von OnMouseMove ab und gibt allen das Event. Das Widget prüft noch ob es im Bereich liegt und Löst eventuell OnEnterMouse/OnLeaverMouse(von IWindow auf IControl verlagert).

_________________
"Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren"
Benjamin Franklin

Projekte: https://github.com/tak2004


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 14 Beiträge ] 
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.014s | 15 Queries | GZIP : On ]