PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Action-Listener (allgemein) aber wie, wo, was?



Jor
14-12-2005, 08:11
Hallo *,

ich möchte gerne etwas Generelles über Action-Listener erfahren, in einem Buch habe ich vier unterschiedliche Beispiele für das Anbinden eines Event gelesen:
1) Frame ist Listener
2) Member-Klasse ist Listener
3) Anonyme Subklasse eines Adapters
4) Anonyme Klasse vom Listener-Interface
Euch erfahrenen Javaleuten werden diese Sachen bestimmt etwas mehr sagen als mir, da ich mich in der Einarbeitung befinde. Meine Fragen:
1) Ist es Geschmackssache, wie ich welchen Listener anbinde? (bestimmt nicht, aber.... )
2) Wie kann ich auf die einfachste Weise eine Listener an einen Button anlöten.
Ich freue mich auf eure Antworten...

mwanaheri
14-12-2005, 12:37
Es ist nicht ganz Geschmackssache, wo man den Listener hinpackt, aber doch weitgehend. Kommt etwas darauf an, wie man die Anwendung organisiert hat. Im Allgemeinen packe ich den Listener in das Panel (oder den Frame), der das Element hat, das reagieren soll.

Ein einfaches Beispiel:

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class HalloButton extends JFrame implements ActionListener{
JButton btn1;
JButton btn2;
public HalloButton(){
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
makeButtons();
arrangeElements();
registerButtons();
}
private void makeButtons(){
btn1 = new JButton("button 1");
btn2 = new JButton("button 2");
}
private void arrangeElements(){
this.setLayout(new FlowLayout());
this.getContentPane().add(btn1);
this.getContentPane().add(btn2);
}
private void registerButtons(){
btn1.addActionListener(this);
btn2.addActionListener(this);
}
public static void main(String[] args){
HalloButton app = new HalloButton();
app.setSize(100,100);
app.setVisible(true);
}
public void actionPerformed(ActionEvent ev){
if (ev.getSource() == btn1)
System.out.println("Button1 gedrueckt");
if (ev.getSource() == btn2)
System.out.println("Button2 gedrueckt");
System.out.println("Ein Event ist aufgetreten");
}
}

wie du siehst, schreibe ich eher mehr Methoden als weniger.
makeButtons() erzeugt die Buttons,
arrangeElements() sorgt für die Anordnung auf dem JFrame und
registerbuttons() registriert den Listener.
Mit diesen Methoden halte ich den Konstruktor übersichtlich.
Wichtig ist die Methode actionPerformed(..). Sie muss da sein, wenn ActionListener implementiert wird. Dort frage ich dann ab, woher das Event kam und lasse die Methode entsprechend handeln.

GUI-Builder arbeiten meistens anders. Sie regisrieren anonyme Listener , die dann eine Methode machDasWennHierGeklicktWurde() (oder so ähnlich) aufrufen.
Dann hat man aber die Sachen über die ganze Klasse verteilt, was ich sehr unpraktisch finde, wenn man den Code auch noch per Hand bearbeiten möchte.

Jor
14-12-2005, 12:53
Hi mwanaheri,

vielen Dank für deine Info! :-))
Wenn ich das jetzt richtig verstanden habe, dann wird ein ActionListener an das HauptFrame gepömpelt( fachterm ;-) ) und die hinzugefügten Komponenten erben diesen? Ich bin auch ein Freund von übersichtlichen Konstruktoren.
Vielleicht wird mir einiges klarer, wenn ich mich gleich mit deinem Script befasse.
Aber man kann sagen, ich kann mir ein oder zwei bevorzugte Weg aussuchen und diese, wenn möglich, nutzen?

Jor
14-12-2005, 13:25
@mwanaheri,

jep, es funzt wie geschmiert!!! Danke nochmal, es ist ein bisschen klarer geworden und ich komme jetzt weiter.
(Wenn auch nur bis zur nächsten Frage ;-)) )

Bis dann...

mwanaheri
14-12-2005, 16:39
Schön, dass es klappt. Was mich jetzt interessieren würde:
Wie halten es denn die anderen hier mit den Listenern? Irgendwelche Daumenregeln, wann was besser ist? Ich hab' da nämlich auch noch Lernbedarf.

ContainerDriver
08-04-2009, 21:18
Darf ich bitte noch um ein paar Antworten bitten? :)

@mwanaheri: hältst du es immer noch so, wie weiter oben von dir beschrieben? Die Idee, den Listener direkt in den Frame zu packen hatte ich nämlich eben auch und dann bin ich auf dein Posting gestoßen.
Bei uns in der Vorlesung hieß es, normalerweise wird der Listener (da steckt ja quasi die Business-Logik drinnen) von der GUI getrennt. Allerdings habe ich da jetzt folgendes Problem: wenn ich den Listener in eine extra Klasse auslagere, dann kann ich innerhalb von actionPerformed() nicht ohne Verrenkungen auf z.B. das Objekt zugreifen, in dem er Frame (und der auslösende Button) sitzt...

peschmae
09-04-2009, 11:16
Bei uns in der Vorlesung hieß es, normalerweise wird der Listener (da steckt ja quasi die Business-Logik drinnen) von der GUI getrennt. Allerdings habe ich da jetzt folgendes Problem: wenn ich den Listener in eine extra Klasse auslagere, dann kann ich innerhalb von actionPerformed() nicht ohne Verrenkungen auf z.B. das Objekt zugreifen, in dem er Frame (und der auslösende Button) sitzt...

Grundsätzlich kommt es natürlich immer darauf an ;)

Ich versuche meist (wobei ich in letzter Zeit sehr wenig GUI-Zeugs gemacht habe, und schon gar nicht mit Java; und wenn dann schon gar nicht mit AWT/Swing...) alles was GUI manipuliert im listener zu halten, weil du darum nicht so einfach herumkommst.

Andererseits ist es durchaus eine gute Idee das was hintenrum läuft in eine eigene Methode (die nichts mit GUI am Hut hat) mit schönem Interface auszulagern, die dann im Listener aufgerufen wird oder so ;)

MfG Peschmä

ContainerDriver
13-04-2009, 20:02
Danke für deine Antwort.

Habe mich jetzt ein bisschen in das MVC-Modell (http://openbook.galileocomputing.de/oo/oo_06_moduleundarchitektur_001.htm#Rxxob06moduleun darchitektur001040015ff1f012130) eingelesen (bzw. lese ich mich gerade ein), das Konzept erscheint mir recht gut.

Weiter oben habe ich geschrieben:


wenn ich den Listener in eine extra Klasse auslagere, dann kann ich innerhalb von actionPerformed() nicht ohne Verrenkungen auf z.B. das Objekt zugreifen, in dem er Frame (und der auslösende Button) sitzt...

nach dem MVC-Modell würden sich View und Controller (=ActionListener) kennen, also wäre da ein Zugriff möglich (oder man macht Änderungen am Modell, was dann der View wieder mitbekommen wird).

Dein letzter Satz, Peschmä, wäre dann die Zusammenlegung von View und Controller (darauf wird auch in dem von mir verlinkten Dokument hingewiesen).

Gruß, Florian

mwanaheri
15-04-2009, 18:33
Noch eine Bemerkung zur Trennung von Gui- und Geschäftslogik:
Absolut sinnvoll. Der Haken ist nur immer die Zugänglichkeit. Irgend etwas muss man weiterreichen. Entweder macht man die Komponenten, mit deren Inhalt man arbeiten will, zugänglich, oder die Geschäftslogik.Da ich meistens mit Datenbank-basierten Anwendungen arbeite, halte ich es gemeinhin so (einfacher Fall):

In einem Panel befindet sich ein button ("save") und (in weiteren Panels organisiert) der zu präsentierende/ändernde Inhalt in Textfeldern. Die Textfelder werden in den Unterpanels zugänglich gemacht (getText/setText), allerdings nur bis zu der Ebene, auf der der Button liegt. Auf der Ebene liegt der ActionListener.Im Listener wird nicht direkt gespeichert. Statt dessen liegt die Speichermethode in einer Singleton- oder Factory-Klasse, die alle Datenbankarbeiten übernimmt. Die Methode führt auch eventuelle Prüfungen aus. Der Listener ruft sie nur auf und holt sich aus den Textfeldern die benötigten Parameter.

Die Geschäftslogik bleibt also -- was die Datenarbeiten anbelangt -- von der Gui-Logik getrennt, ist aber auf diese Weise ansprechbar.

Wenn man es etwas raffinierter haben will, kann man auch im ActionListener ein weiteres selbst definiertes ActionEvent schmeißen, dem man die notwendigen Dinge mitgibt. Diese Action kann dann weiter "oben" verarbeitet werden.

mamue
21-04-2009, 08:18
Das MVC ist IMHO ein brauchbarer Ansatz. Manchmal trenne ich das ein wenig weiter und gebe die Events an Adapter weiter. Diese Adapter kennen das Model und somit kann man danach das View getrennt entwickeln. Ich würde eigentlich nicht einen Listener an mehrere Quellen hängen, sondern jede Quelle (z.B. jede JButton instanz) mit einem eigenen Listener versehen. Das Model selbst wäre in dem Ansatz übrigens Quelle für Change-Events. Wer mag, kann sich auch mal MVP (model view presenter) ansehen.

HTH
mamue