# Trennung Gui und Anwendungslogik



## odysseus (13. Jan 2004)

http://141.56.132.162/lehre/webapps/javabuch/k100179.html#mediatorinjava

Dieses Beispiel kennt ihr doch sicher alle aus dem GotoJava2. Hats auch wer verstanden ?

ich sehe das so:

einerseits muss die Gui ein Objekt der Command-Klasse erhalten damit die EventListener sich bei Ihr registrieren können:


```
addKeyListener(cmd);
```

andererseits muss die ClientCommand über ein Objekt der Gui verfügen um sie zu steuern!
Ich weiss das ich, sobald ein Event ausgelöst wird, vom Event mit getParent().getParent().getParent irgendwann die Gui selbst erreiche,
aber ohne einen Event als Ausgangspunkt geht das nicht.

Wenn ich jetzt aber, z.b. Daten von einem Server empfange und sie an eine TextArea in der Gui anhängen will ??

Ich habe keinen Event, hab also keinen Zugriff auf die Gui.

Wo ist der Denkfehler ?
Kann mich wer aufklären ?

thx


----------



## Kerberus (13. Jan 2004)

Hast du eigentlich  meine E-Mail erhalten?


----------



## odysseus (13. Jan 2004)

oh, hab sie gerade aus dem spam bei web.de rausgefischt 

danke.

ich studier das jetzt mal...


----------



## odysseus (14. Jan 2004)

ich hab das problem doch nicht lösen können.

Es bleibt ein Teufelskreis:

Die Gui braucht die Command, die Command braucht die Gui, geht nicht...
Es reicht doch nicht, das die Command auf Events reagieren kann, die Command muss auch ohne Event Zugriff auf die Gui haben...


----------



## bummerland (14. Jan 2004)

wenn du deine eigene listener-klasse hast, ist das doch kein problem, oder? 
in deiner gui-klasse legst du dein listener-objekt an.
im konstruktor der listener-klasse übergibst du deine gui, z.b. das frame oder so. somit kannst du in der listenerklasse auf die gui zugreifen und umgekehrt auch.

ist es das, was du meintest?


----------



## stev.glasow (14. Jan 2004)

odysseus hat gesagt.:
			
		

> ich hab das problem doch nicht lösen können.
> 
> Es bleibt ein Teufelskreis:
> 
> ...



und wenn du es in der art machst:


```
import javax.swing.*;
import java.awt.event.*;
import java.util.*;

public class test
{
    public static void main(String[] ars)
    {
        Gui g = new Gui();
        Cmd c = new Cmd();
        g.addObserver(c);
    }
    
}

class Cmd implements Observer
{
    public void update(Observable o, Object arg) 
    {
        Gui g = (Gui)o;
        ActionEvent e = (ActionEvent)arg;
        System.out.println(e.getActionCommand());
        
        // ... hier kannst du dann mit dem ActionEvent e arbeiten .
        // ... und das Gui-Object steht dir auch zur verfügung
        
    }
    
}

class Gui extends Observable implements ActionListener
{
    public Gui()
    {
        JFrame f = new JFrame();
        JButton b = new JButton("tach");
        b.addActionListener(this);
        f.getContentPane().add(b);
        f.show();
    }
    
    public void actionPerformed(ActionEvent e)
    {
        setChanged();
        notifyObservers(e); 
        
    }
}
```


----------



## odysseus (14. Jan 2004)

becstift hat gesagt.:
			
		

> wenn du deine eigene listener-klasse hast, ist das doch kein problem, oder?



inzwischen hab ich eine eigene ListenerMethode angelegt, EventHandling, diese implementiert ActionListener und KeyListener und empfängt die Events von der Gui.

das ist kein Problem. 


```
public void actionPerformed(ActionEvent e) {
       if (e.getActionCommand() == "Connect") {
       Button b = (Button) e.getSource(); // jetzt kann ich den Button bedienen
       //wenn ich wollte könnte ich mit b.getParent() auch noch weiter gehen und die ganze Gui bedienen.

       //nehmen wir an, ich will jetzt noch eine methode von ClientCommand aufrufen, um einen Server zu connecten
       //wie ??
}
```

ok, ich kann die gui steuern wenn ich einen Event empfangen habe.

aber ich will ja mehr als die Gui steuern. ich will jetzt natürlich noch eine Aktion ausführen, dazu muss ich auch Zugriff auf ClientCommand haben!!
ausserdem bin ich ohne einen Event als Ausgangspunkt völlig geliefert und kann garnichts steuern, weder gui noch Command...

ich probier mal aus was Du gesagt hast.. und melde mich dann nochmal..



			
				becstift hat gesagt.:
			
		

> im konstruktor der listener-klasse übergibst du deine gui



der Listener hat sowieso Zugriff auf die Gui, wenn er Events empfängt. D.h. wenn der User einen Button klickt, kann ich den Button schön bunt machen, damit der User sich freut, aber er wird enttäuscht wenn sonst nichts mehr passiert, deswegen brauch ich auch Zugriff auf ClientCommand...

*headbanging*


----------



## odysseus (14. Jan 2004)

@stevg:

ich muss mir erst mal anschauen was ein Observer ist. dauert ne weile.

danke für die Mühe.
pz.


----------



## stev.glasow (14. Jan 2004)

odysseus hat gesagt.:
			
		

> @stevg:
> 
> ich muss mir erst mal anschauen was ein Observer ist. dauert ne weile.
> 
> ...



schau mal hier http://www.galileocomputing.de/openbook/javainsel/java-11.htm#t214 . dort gibt es unter der überschrift "Ein Design-Pattern durch Beobachten von Änderungen" eine ganz kurze einführung zu diesem thema


----------



## odysseus (14. Jan 2004)

so, ich habs jetzt hinbekommen.  8) 

ich werd versuchen das aufzubereiten, vielleicht in einem klassendiagramm, wenn ich ne software finde die das generiert, falls nicht versuch ichs eben anders darzustellen.

hat wer nen tipp für ne java design software, die aus klassen ein klassendiagramm erstellt ?

möglichst freeware, möglichst für linux.

hier schon mal der entscheidene teil:

```
public ClientGui(ClientCommand cmd){//konstruktor
super("odysseus");
EventHandling eh = new EventHandling(cmd);
//eventhandling implementiert die listener
//eh ist der Listener der sich bei den GuiElementen registriert
//eh erhält im Konstruktor ClientCommand um die Methoden zu nutzen
```


----------



## pcKOAL (15. Jan 2004)

*Hallo stevg*

Ich hab mich laut Deinem Vorschlag
ebenfalls erkundigt was ein Observer ist
hab mir auch gleich den Source-Code der Observable-Class angesehen

jetzt frag ich mich nur, welchen Sin hat eigentlich die setChanged() Methode
wenn diese nicht gesetzt ist geht das Objekt von notifyObservers() verloren


nächste Frage:
gibt es auch sowas wie eine ThreadObservable-Class?
es wäre doch gut wenn ein Thread den zuhörer-Tread informiert
und nicht selbst in diesem herumgurkt.


mfg. pcKOAL


----------



## stev.glasow (15. Jan 2004)

pcKOAL hat gesagt.:
			
		

> jetzt frag ich mich nur, welchen Sin hat eigentlich die setChanged() Methode
> wenn diese nicht gesetzt ist geht das Objekt von notifyObservers() verloren.


ohne setChanged() würde in notifyObservers()  nicht die methode update(Observable o, Object arg) der zuhörer (Observer)  aufrufen werden.




			
				pcKOAL hat gesagt.:
			
		

> gibt es auch sowas wie eine ThreadObservable-Class?
> es wäre doch gut wenn ein Thread den zuhörer-Tread informiert
> und nicht selbst in diesem herumgurkt.




```
class YourThreadObservable extends Observable implements Runnable
{
 ...
}
```
klar ?



und falls es nicht so rüber gekommen ist (ich schrieb: "in der art"): das obige beispiel mit der Gui und Cmd sollte nur einen denkansatz geben und sollte nich so in eigene projekte übernommen werden.


----------



## pcKOAL (16. Jan 2004)

...




			
				stevg hat gesagt.:
			
		

> ohne setChanged() würde in notifyObservers()  nicht die methode update(Observable o, Object arg der zuhörer (Observer)  aufrufen werden



ja, schon klar!
aber vor jedem aufruf der Methode notifyObservers() muss die Methode setChanged() aufgerufen werden.
wenn ich das Beispiel aus GalileoComputing, mit dem Witze erzähler auf der Party, her nehme
wäre für mich der einzige Sin darin, dass eine externe Klasse zum Witzeerzähler sagt erzähl mal
und je nach belieben sagt er zuvor setChanged() damit ihm auch andere zuhören
sagt er aber nicht setChanged() blast der witze Erzähler alles in die Luft
das kann aber doch auch so gelöst werden, 
dass die externe Klasse beim Aufruf des "erzähl mal" einen Flag mit gibt (erzähl/blas in die Luft)
so braucht die Observable Klasse das setChanged Flag nicht

ich fersteh nur die Logik nicht
warum soll ich immer zwei Methoden aufrufen





			
				stevg hat gesagt.:
			
		

> ```
> class YourThreadObservable extends Observable implements Runnable { ... }
> ```



Ja sicher,
aber das heißt nur das die Observable Klass selbst rennt
und wenn dann ein anderer Thread zu ihm sagt notyfyObservers()
benachrichtigt eben dieser andere Thread die Klassen
und nicht der YourThreaObbervable-Thread!




			
				stevg hat gesagt.:
			
		

> das obige beispiel mit der Gui und Cmd sollte nur einen denkansatz



ist mir eh klar,
Dabei hab ich ja schon wieder etwas dazugelernt   
und mir ist wieder tolle neue Fragen eingefallen
*gestern* hab ich noch schnell so einen Thread geschrieben, dem man sagen kann tu das und das
und der dann selbstständig abworkt.


mfg. pcKOAL


----------



## stev.glasow (16. Jan 2004)

> Ja sicher,
> aber das heißt nur das die Observable Klass selbst rennt
> und wenn dann ein anderer Thread zu ihm sagt notyfyObservers()
> benachrichtigt eben dieser andere Thread die Klassen
> und nicht der YourThreaObbervable-Thread!


den fall das fremde klassen die notyfyObservers() aufrufen können hast du doch immer (außer du überschreibst diese und setzt sie z.B. auf private) 
aber die YourThreaObbervable selbst kann doch immer die notyfyObservers() aufrufen. z.B. in 'public void run() '.
oder habe ich dich missverstanden und das war garnicht dein problem

und zur setChanged():
da ja die notyfyObservers() auch von außerhalb aufgerufen werden kann und die klassen, die dies tun, nicht wissen können ob überhaubt änderungen aufgetreten sind wird dieser flag benutzt (würde ich sagen, berichtigt mich wenn ich falsch liege)  - die anderen klassen können zwar sagen das die zuhörer benachricht werden sollen, aber im endefekt geschieht dies nur wenn das flag auch von der Observable gesetzt wurde, was meines erachtens auch sinn macht.
klar was ich meine ?


----------

