# In externer Eventhandlerklasse auf GUI-Elemente zugreifen



## blabla2k (31. Mrz 2009)

Hallo,

folgende Situation, zur Veranschaulichung möglichst einfach dargestellt:

Ich habe eine Benutzeroberfläche mit einem Button. Dieser Button soll auf einen Klick reagieren. Zu diesem Zweck füge ich ihm einen Eventlistener hinzu. Der Handler dafür soll in eine externe Klasse, da er relativ viel Programmlogik enthält und daher aus Gründen der sauberen Programmierung von der GUI getrennt werden soll.

In diesem Handler will ich auf verschiedene Elemente (Textfelder, Listen...) der Benutzeroberfläche zugreifen. Diese Elemente sind im Eventhandler natürlich erst mal nicht zugänglich. Jetzt habe ich überlegt, wie ich das anstellen könnte, aber habe keine Methode gefunden die mich wirklich zufriedenstellt:


*1. Die betreffenden Steuerelemente in der Formularklasse als statisch definieren, dann der GUI-Klasse entsprechende statische get-Methoden hinzufügen. Dann kann ich im Handler so darauf zugreifen: TestForm.getInfoTextField().getText()*

Diese Lösung ist deshalb nicht so gut, weil die Steuerelemente eigentlich nicht statisch sein sollen. Vielleicht soll es ja mehrere Instanzen der Formularklasse(n) geben.

*2. Der Formularklasse get-Methoden für die Formulare hinzufügen und dann dem Eventhandler eine Instanz der Formularklasse im Konstruktor übergeben.*

Funktioniert an sich gut, aber was ist, wenn ich im Eventhandler auch noch auf andere Formulare zugreifen will als die, die den Eventlistener angemeldet haben? Es kann sein, dass von diesen Formularen noch gar keine Instanz vorhanden ist, wenn ich den Eventlistener anmelde, also kann ich diese Formulare nicht dem Eventhandler übergeben.
*
3. Formulare als Singleton-Klassen definieren und dann im Eventhandler die jeweilige Instanz abholen*

Funktioniert an sich auch gut, aber hat wiederum die Limitierung, dass es nur eine Instanz jedes Formulares geben kann.

*4. Die Steuerelemente direkt dem Konstruktor des Eventhandlers übergeben*

Auch eine Möglichkeit, ist aber inakzeptabel, wenn eine große Anzahl von Steuerelementen zugänglich gemacht werden sollen.



Also das sind die Möglichkeiten die mir bisher eingefallen sind. Vielleicht sind auch einige davon völlig verpönt oder ungebräuchlich, aber ich tue mich echt schwer eine Lösung zu finden. Es soll auch nicht einfach nur funktionieren, sondern möglichst elegant und effizient gelöst werden.


----------



## Marco13 (31. Mrz 2009)

Vergiß' static und Singleton. 

Eine "Mischung" aus 2 und 4 ... eher in Richtung 2 gehend, wo ich das Problem nocht nicht verstanden habe... du hast also eine Klasse
class MainControl extends JPanel ...
mit ein paar Buttons, TextFields und so drauf, und willst jetzt an einen Button einen 
class Handler implements ActionListener
oder so hängen, der u.a. auch auf die TextFields zugreift? Dann kann dieser Handler (ggf. gleich im Konstruktor) das "MainControl" übergeben bekommen.

Und wenn ich es richtig verstanden habe, kann es jetzt eine andere Klasse geben
class OtherControl extends JPanel
die andere TextFields oder so enthält, und auf die der Handler AUCH zugreifen muss? Falls das das Problem ist, stellen sich 2 Fragen: Was passiert, wenn dieses zweite Panel nicht erstellt wird (also, ist das "überlebenswichtig" für den Handler?) und wer erstellt diese beiden Panels (MainControl und OtherControl)? GGf. könnte DERjenige ja auch den Handler erstellen, und die beiden Panels dann an den Handler übergeben ... sinngemäß sowas wie

```
class Main
{
    void doit()
    {
        ControlPanel a = new ControlPanel(); 
        OtherPanel b = new OtherPanel();
        Handler h = new Handler(a,b);
        a.addAsListener(h);
    }
}
```
(ganz, ganz grob ... ggf könnte das "OtherPanel" auch später mit einer set-Methode an den Listener übergeben werden oder so ... das hängt dann mit der ersten Frage zusammen...)

    }


----------



## blabla2k (31. Mrz 2009)

Hallo Marco,

danke für die schnelle Antwort 

Ich lese gleich in Ruhe deine Antwort, ich schreibe erstmal schnell wie es konkret sein soll:

Ich habe zwei Formulare, ein MainForm und ein DialogForm (DialogForm wird mit einem Button aus der MainForm geöffnet, dort kann man dann einige Optionen setzen die sich auf die MainForm auswirken, und dann schließt man es wieder).

Im DialogForm ist dann beispielsweise ein Button, und wenn man den anklickt, sollen gewisse Steuerelemente sowohl in der MainForm als auch in der DialogForm  aktualisiert werden. Der Eventhandler dafür muss also auf beide Formulare zugriff haben.

Sollte ich dann vielleicht ein Feld MainForm der DialogForm-Klasse hinzufügen, das dann per Konstruktorübergabe gesetzt wird, wenn MainForm eine Instanz von DialogForm erstellt? Also:
new DialogForm(this)

und dann wenn ich in DialogForm den Eventhandler anmelde, könnte ich beide Formulare übergeben:
this (das DialogForm selbst) und this.MainForm (das Hauptformular, was ich per Konstruktor übergeben habe). So hätte der Eventhandler, der in DialogForm angemeldet wird, beide Formulare zur Verfügung.
Würde man das so machen? Es würde bestimmt gehen, aber es kommt mir irgendwie frickelig vor.

Der Fall, dass das zweite Panel (also in diesem Fall MainForm) nicht vorhanden ist, wird logischerweise nie eintreten, da es ja selber das erste Panel erstellt. Also wäre zumindest das kein Problem.


Noch eine kleine Frage direkt zu den Formularen: Sollte man jedesmal, wenn der Benutzer aus dem MainForm das DialogForm aufruft, eine neue Instanz der DialogForm erstellen, und diese dann wieder zerstören wenn es geschlossen wird? Oder sollte man schon beim Laden von MainForm eine Instanz von DialogForm erstellen und diese dann nur sichtbar und unsichtbar machen?


----------



## Marco13 (4. Apr 2009)

Hm. Erstmal kurz zum letzten Punkt: Das hängt davon ab, ob das immer wieder der selbe oder immer wieder der gleiche Dialog ist. Wenn man immer wieder den selben Dialog verwendet, stehen dort natürlich ggf. noch die Eingaben vom letzten Öffnen drin. Das kann erwünscht sein, oder nicht.


Und sonst: Man könnte jetzt etliche mögliche Abstraktionen vorschlagen. Nur kann es gut sein, dass die ein Overkill wären. Wird diese DialogForm immer von der MainForm aus geöffnet? Kann man mit 100%iger Sicherheit sagen, dass die DialogForm NIE existieren wird, wenn es die MainForm nicht gibt? Dann kann die DialogForm auch die MainForm im Konstruktor übergeben bekommen.
Wenn die DialogForm aber auch von "irgendwo anders aus" geöffnet werden kann, und dort ggf. garkeine MainForm verfügbar ist, KÖNNTE(!) eine andere Struktur sinnvoller sein. (Ob man dann ggf. dem Konsruktor einfach 'null' übergeben könnte, müßte man sich überlegen...)


----------

