Event Handling - nur wie ???



  • Hallo zusammen!

    Hat jemand von Euch eine Vorstellung davon, wie unter Java (meinetwegen in Swing) das Konzept des Event-Handlings realisiert wurde?

    Ich gehe mal davon aus, dass Source-Objekte im Haupt-Thread Events werfen, die dann in einem anderen Thread interpretiert werden (Es werden also Listener mit Folgebefehlen angesteuert) Darauffolgend können dann wieder weitere Events geworfen und erneut durch einen weiteren Thread ausgewertet werden. Es gäbe somit für jede Ebene dieses "Event-Baumes" einen Thread, der die Event-Objekte dieser Ebene auswertet.
    OK, das ist jetzt nur so ne Idee! Wär ja möglich!

    Nur wie wird sowas denn nun wirklich realisiert? Event-Handling ist ja nichts Neues! Zumindest jede GUI-Bibliothek bietet Ereignisbehandlung an.

    Nur wie funktioniert's?

    Hat jemand von Euch eine grobe Vorstellung davon?

    Grüße,
    TS++



  • Hat jemand von Euch eine Vorstellung davon, wie unter Java (meinetwegen in Swing) das Konzept des Event-Handlings realisiert wurde?

    Ja, mich wundert allderdings, was dich davon abhält, das kurz in den Sun-Tutorials nachzusehen.
    Wie auch immer, im Groben läuft das so ab, dass du von einer Listener-Klasse ableitest (MyFooBarButtonListener), dabei Methoden, die z.B. bei klick aufgerufen werden, redefinierst.
    Dann registrierst du Instanzen von diesen Listenern bei den einzelnen Steuerelementen.
    Das sieht etwa so aus:

    myButton.addListener(new MyFooBarButtonListener());
    

    Damit man nicht 9826347 verschiedene Listenerklassen im Programm hat, bieten sich dafür anonyme Klassen an.



  • Danke für Deine Antwort!

    Ich denke nur, Du hast mich wahrscheinlich falsch verstanden!
    Mit der Anwendung der EventListener in Swing bin ich bereits mehr oder weniger vertraut. Ich bin daran interessiert, zu erfahren, WIE das EventHandling implementiert wurde. Natürlich wird kein Mensch entsprechenden Quellcode offenlegen! Nur es hätte ja sein können, dass jemand von Euch schon einmal entfernt Notiz vom Funktionsprinzip des EventHandlings genommen hat. (muss natürlich nicht unbedingt Swing sein)
    Evtl. handelt es sich dabei ja um nichts weiter als um mehrerer Threads, die einzelnen Objekten Befehle erteilen, worauf wiederum als Reaktion andere Threads ihre Arbeit aufnehmen.

    Hat schon einmal jemand etwas davon gehört, wie Ereignisbehandlung auf Thread-Ebene realisiert werden könnte?

    Grüße,
    TS++



  • Generell wird das wohl gleich sein wie bei vielen anderen APIs mit Eventhandling, es gibt eine Schleife in der Nachrichten abgefragt werden ob irgendwas gedrückt wurde und wenn was gedrückt wurde wird die Funktion gestartet die für dieses Ereigniss gestartet werden soll...



  • Swing oder AWT sind doch nur Wrapper um betriebsystemspezifische Funktionen. Eine Windows-VM benutzt halt das Windows-API, so wie du es selber auch tun könntest.
    Sei doch froh, dass du dich um den Kram nicht kümmern musst. 🙂



  • Danke für Eure Antworten!

    Klar bin ich froh, dass ich mich nicht selbst darum kümmern muss, ob irgendeine Taste gedrückt oder die Mouse bewegt wurde! 🙂

    Ich mache mir nur Gedanken darüber wie eigens definierte Ereignisse in einer Anwendung behandelt werden könnten. z.B.: Ich belege ein Objekt A mit einem Namen ( per setName(String)). Als Reaktion auf diese Namensänderung sollen dann weitere Objekte B und C ebenfalls einer Namensänderung unterzogen werden. Natürlich kann man bei dem einfachen Beispiel jetzt auf die Idee kommen, die setName()-Routinen von B und C einfach direkt in der setName()-Methode von A aufzurufen. Klar, grundsätzlich simpelste Kommunikation zwischen Objekten.

    Nur jetzt kommt das grosse ABER 😉
    Der ganze Vorgang würde in ein und demselben Thread, dem Main-Thread, stattfinden!
    Nun wo ist dabei das Problem?
    Verfügen die einzelnen im Rahmen des EventHandlings zum Einsatz gebrachten Methoden über relativ wenig Quellcode (s. setName(String) ) und kann die Abarbeitung dieser Routinen somit relativ schnell von statten gehen, so kann man es verschmerzen, dass ereigniserzeugende Routinen erst auf die Beendigung der ereignisbehandelnden Routinen warten müssen, bevor sie fortfahren können.
    Werden diese Ereignis-Folgeaktions-Bäume allerdings größer und werden die einzelnen Routinen evtl. umfangreicher, so kann man bei den zwangsläufig auftretenden zeitlichen Verzögerungen wohl kaum noch von EventHandling sprechen!
    Lösung: Multi-Threading!
    Auslöser laufen in einem und Ereignisbehandler in einem anderen Thread, so dass die Auslöser der Ereignisse nicht mehr auf die Beendigung von Folgeaktionen warten müssen. Die Ereignisbehandlung würde dann endlich realistischer ablaufen!

    Ich vermute mal, dass auch GUI-Bibliotheken diesen Weg gehen, oder?

    Grüße,
    TS++



  • Die ganze Ergeignisbehandlung läuft in Java in einem anderen Thread, der immer schläft, wenn er nichts zu tun hat. Der nennt sich event-dispatching thread. Es ist also tatsächlich so, dass der Code der Listener in einem eigenen Thread läuft.

    Bei .Net kann ich es dir nicht mit Sicherheit sagen. Ein Standard-Windowsprogramm ruft in seiner Main-Funktion eine Methode auf, die den aktuellen Thread als Nachrichten-Thread benutzt und nicht mehr zurückkehrt.
    Du gibst praktisch an, in welchem Thread das laufen soll.

    Wenn du nebenbei was anderes machen willst, kommst du eh nicht um Threads herum.



  • Die ganze Ergeignisbehandlung läuft in Java in einem anderen Thread, der immer schläft, wenn er nichts zu tun hat. Der nennt sich event-dispatching thread. Es ist also tatsächlich so, dass der Code der Listener in einem eigenen Thread läuft.

    Wenn also jetzt meinetwegen ein Mouse-Down-Event bei einem Button stattgefunden hat, dann könnte der Button vielleicht (vom Main-Thread aus) ein Ereignisobjekt für das Mouse-Down in einen speziellen Zwischenspeicher ablegen (vielleicht eine Queue). Ein Semaphore sorgt dann dafür, dass der schlafende event-dispatching thread aufgeweckt wird sobald ein neues Ereignis in der Queue abgelegt wird. Dann entnimmt der Thread das Event-Objekt aus der Queue und verarbeitet es. Er stößt also alle Folgeaktionen an. In dem Eventobjekt könnten ja Verweise auf bestimmte Zielobjekte und deren Methoden vorhanden sein, so dass als Folge des Mouse-Down z.B. ein Panel grün gefärbt wird. Nur wenn jetzt bei diesem Grünfärben wieder ein weiteres Ereignis ausgelöst wird, wer verwertet denn dann dieses Ereignis. Der Main-Thread kann es nicht sein und auch der event-dispatching-thread kann es nicht sein, denn sonst müssten Button und Panel ja beide warten, bis das neu geworfene Event behandelt wurde. Es müsste also ein weiterer Thread her, der das neue beim Färben ausgelöste Event behandelt.
    Nur, um Gottes Willen, wieviele Threads brauche ich denn da im schlimmsten Fall? Und richtig ekelhaft wird der Ansatz erst, wenn ich es mit Endlosschleifen zu tun habe. (wenn also eine Folgeaktion immerwieder das vorhergehende Event auslöst)

    Bei der Geschichte gibt's bestimmt noch nen Trick! Nur welchen???? 😕

    Grüße,
    TS++



  • IMHO:
    Die Events werden alle gespeichert und in der Reihenfolge, in der sie auftreten nacheinander im selben Thread behandelt. Wenn also das Grün färben ein Event auslöst, dann wird dieser neue Event hinten eingereiht.



  • Hm, könnte vielleicht wirklich so funktionieren! Wahrscheinlich verkomplizier ich das Problem nur wieder mal.

    Du meinst also wir haben nicht mehr und nicht weniger als 2 Threads. Den Main-Thread und den event-dispatch-thread.
    Wenn wir mal wieder das vorherige Button-Panel-Grünfärben-Beispiel 😉 betrachten, so müsste das doch folgendermaßen funktionieren:

    im Main Thread:
    - Button und Co werden im Main-Thread erzeugt
    - Button wirft Mouse-Down-Event
    - Mouse-Down-Event wandert in eine zentrale Queue

    im event-dispatch-thread:
    - event-dispatch-thread wacht auf und nimmt Event aus Queue
    - event wird verarbeitet -> d.h.: Panel wird grün gefärbt
    - das Grünfärben verursacht ein weiteres Event
    - neues Event wird in Queue eingefügt
    ... usw

    Das Dumme ist ja jetzt nur, dass wirklich alle Folgeereignisse im Rahmen des event-dispatch-threads geworfen und verarbeitet werden! 😞
    D.h. also, dass lediglich die Objekte, die die Lawine ins Rollen gebracht haben (hier unser Button) quasiparallel zu den Folgeaktionen arbeiten!
    Auslöse- und Folgeaktionen die im Rahmen des event-dispatch-threads stattfinden, werden richtig schön sequentiell abgearbeitet. D.h. in unserem Beispiel wird das Grünfärben des Panels erst vollständig abgeschlossen und dann erst können Folgeereignisse verarbeitet werden.

    Ist natürlich die Frage, ob das effizient genug ist?
    Funktionieren müsste der Ansatz eigentlich!

    Grüße,
    TS++



  • So wird es auf jeden Fall bei AWT/Swing gemacht. Ich habe doch keine Ahnung, ob das für dein Problem jetzt angemessen ist, oder willst du vielleicht ein GUI-API schreiben? Das würde ich lieber lassen...



  • Also ich kann Dich beruhigen, eine GUI-API werd ich mit Sicherheit nicht schreiben. Gibt ja eh schon genug! 😉

    Ich wollte einfach das Zusammenspiel von Objekten etwas realistischer machen. Schließlich verwenden wir ja das Konzept der Objektorientierung um Szenarien der realen Welt nachzubilden. Da liegt es doch nah, von dem klassischen Ansatz Subroutinen aufzurufen abzurücken und etwas bei Mutter Natur abzukupfern. Und das Konzept des EventHandlings besteht ja schon einige Zeit, leider häufig nur in Verbindung mit grafischen Benutzeroberflächen!

    Ich möchte meine Anwendungen etwas "intelligenter" und realitätsnaher entwickeln.

    Der Ansatz mit den 2 Threads löst auf jeden Fall die schwerwiegendsten Probleme des EventHandlings. Es sind sogar Endlosschleifen möglich! 🙂
    Ich bin nur etwas am zweifeln, ob der event-dispatch-thread nicht in die Knie geht, wenn die Anzahl an Events exponentiell stark zunimmt!

    Grüße,
    TS++


Anmelden zum Antworten