7 days of WordPress plugins, themes & templates - for free!* Unlimited asset downloads! Start 7-Day Free Trial
Advertisement
  1. Code
  2. ActionScript

AS3 101: Ereignisse - Basix

Read Time: 32 mins
This post is part of a series called AS3 101.
AS3 101: OOP - Introducing Design Patterns
AS3 101: Quick Tip - Dispatching Events Without Extending EventDispatcher

German (Deutsch) translation by Federicco Ancie (you can also view the original English article)

In diesem Kapitel von AS3 101 werden wir in die Mechanik des Flash-Ereignissystems eintauchen. Wenn Sie bisher mitverfolgt haben, haben Sie Ereignisse im Einsatz gesehen, die bis in die erste Episode der Serie zurückreichen. Der Redakteur und ich waren der Meinung, dass es an der Zeit war, etwas zu schreiben, das offiziell in den Lehrplan aufgenommen werden sollte Tutorial für Sie.

Es gibt bereits ein Activetuts+-Tutorial zu den Grundlagen von Events, daher liegt der Schwerpunkt dieses Tutorials auf dem Dispatching von Events aus Ihren eigenen Klassen, einschließlich der Erstellung benutzerdefinierter Event-Typen und -Objekte.

Um mit diesem Tutorial erfolgreich zu sein, sollten Sie mit dem Schreiben und Verwenden Ihrer eigenen Klassen in ActionScript 3 vertraut sein und sich mit der Verwendung der vorhandenen Flash-Ereignisse wie MouseEvent.CLICK oder Event.ENTER_FRAME sicher fühlen. Wir werden uns in erster Linie darauf konzentrieren, benutzerdefinierte Ereignisse aus benutzerdefinierten Klassen zu versenden.


Vorschau

Wir werden für dieses Tutorial viel Zeit mit der Theorie verbringen, aber am Ende bauen wir ein einfaches Schieberegler-Steuerelement, das seine eigenen Ereignisse auslöst:


Schritt 1: Warum Event-Dispatching verwenden?

Dieses Beispiel ist eigentlich ein ziemlich einfaches Beispiel dafür, warum Sie Ihre eigenen Ereignisse versenden möchten. Wenn Sie Ihre eigenen Klassen schreiben, halten Sie sie idealerweise in ihren eigenen Blackboxen und gekapselt. Aber Sie müssen immer noch die verschiedenen Objekte zusammenarbeiten lassen, um ein nützliches Programm zu erstellen.

Das von ActionScript 3 bereitgestellte Ereignismodell ist eine ziemlich gute und bequeme Möglichkeit, die Kommunikation zwischen Ihren Klassen zu erleichtern und gleichzeitig die Zuständigkeiten in Ihren Klassen zu trennen. Wenn wir also unsere eigene benutzerdefinierte Klasse schreiben, wie die oben gezeigte ActiveSlider-Klasse, müssen wir anderen Objekten ermöglichen, sich bewusst zu machen, wenn der Slider seinen Wert ändert. Wenn der Schieberegler sein eigenes Änderungsereignis senden kann, können andere Objekte, die diese Informationen kennen müssen, problemlos abonnieren und benachrichtigt werden.

Ich persönlich finde die Notwendigkeit, meine eigenen Ereignisse in meinen Klassen zu verteilen, so häufig, dass meine Klassenvorlage jede neue Klasse mit der dafür notwendigen Boilerplate einrichtet. Wenn Sie lernen, Objekte diskret zu halten, wenden Sie sich dem Ereignis-Dispatching als der gebräuchlichsten Methode zu.


Schritt 2: So versenden Sie Ihre eigenen Events

Ich habe gute Nachrichten: Das Versenden eigener Events ist eigentlich ganz einfach. Dies ist einer der Kernpunkte von ActionScript 3, der in den Flash Player integriert ist, und als solcher müssen Sie nur eines tun, um die Fähigkeit zum Versenden von Ereignissen zu erlangen. Diese eine Sache ist:

EventDispatcher erweitern

Das war's: Verwenden Sie beim Schreiben Ihrer Klasse die Zeile:

Natürlich müssen Sie EventDispatcher importieren, der sich im flash.events-Paket befindet. Sie werden wahrscheinlich andere Klassen im Paket benötigen, daher ist es möglicherweise am bequemsten, das Paket einfach mit einem Platzhalter zu importieren.


Schritt 3: Versand

Jetzt sind Sie zum Versenden eines Ereignisses eingerichtet. Jetzt müssen Sie nur noch eine von EventDispatcher bereitgestellte Methode namens "dispatchEvent" aufrufen. Leicht zu greifen, nicht wahr?

Wenn Sie dispatchEvent aufrufen, müssen Sie mindestens ein Argument bereitstellen, ein Event-Objekt. Alle integrierten Event-Objekte befinden sich im flash.events-Paket, daher ist der Wildcard-Import hier praktisch. Jeder Event-Objekttyp hat seine eigenen Anforderungen, aber meistens müssen Sie ihm auch nur ein Argument übergeben. Dieses Argument ist der Ereignistyp, bei dem es sich um einen String handelt, der das Ereignis benennt, z. B. "click" oder "complete". Diese werden häufiger als MouseEvent.CLICK oder Event.COMPLETE geschrieben, aber das Endergebnis ist dasselbe; Es ist ein Bezeichner, der einen Ereignistyp von einem anderen trennt und es einem Event-Objekt ermöglicht, mehrere Ereignistypen zu verwalten.

Wenn Sie also alles zusammenfassen, wenn Sie ein "complete" Ereignis versenden möchten, können Sie dies wie folgt tun:

Ziehen Sie diese Zeile (oder eine ähnliche) einfach in die Methode, die in Ihrer Klasse geeignet ist. Ihre Klasse verwendet dann ihr geerbtes Event-Dispatching-System und alle Listener werden für Sie benachrichtigt. Apropos Hörer, werfen wir auch einen kurzen Blick auf diese.


Schritt 4: Hören Sie zu

Jedes andere Objekt in Ihrer Anwendung kann jetzt auf Ihre benutzerdefinierten Ereignisse warten. Eine weitere gute Nachricht: Dies ist nicht anders als die Anmeldung zu Veranstaltungen für die integrierten Klassen. Im vorherigen Schritt haben wir unsere hypothetische Klasse eingerichtet, um ein COMPLETE-Ereignis auszulösen. Um auf dieses Ereignis zu hören, könnten wir diese Zeile an anderer Stelle in unserem Programm schreiben:

Und das ist es. Dies sollte jedem bekannt vorkommen, der zum Beispiel einen COMPLETE-Listener mit einem Loader verbunden hat, daher werde ich hier nicht weiter darauf eingehen.


Schritt 5: Wohin zu versenden

Wo Sie die Codezeile "dispatchEvent" tatsächlich platzieren, erfordert einige Überlegungen. Normalerweise sollte es die letzte Codezeile der Methode sein, in der es geschrieben wird. Auf diese Weise kann jeder andere Code, der ebenfalls in dieser Methode ausgeführt wird, Eigenschaften festlegen oder den internen Zustand des Objekts auf andere Weise aktualisieren. Durch den Versand nach Abschluss dieser internen Aktualisierung befindet sich das Objekt zum Zeitpunkt des Versands in einem "sauberen" Zustand.

Betrachten Sie zum Beispiel unser Arbeitsbeispiel. Nehmen wir an, beim COMPLETE-Ereignis dreht sich alles um die Verarbeitung einiger Daten; eine Menge von Daten, die so groß ist, dass die vollständige Verarbeitung mehrere Sekunden dauert. Der Zweck des Objekts besteht also darin, die Verarbeitung asynchron zu verarbeiten, um die Benutzeroberfläche nicht zu blockieren. Und wir senden das COMPLETE-Ereignis, um zu sagen, dass die Daten verarbeitet wurden.

Nehmen wir nun an, dass die fragliche Hauptmethode ungefähr so ​​​​aussieht:

OK, nicht sehr realistisch, aber es veranschaulicht den Punkt. Wir bauen die internen Daten so lange auf, bis eine andere interne Logik feststellt, dass wir fertig sind, und schreiben dann einige letzte Datenbits aus, um die Operation abzuschließen.

Fügen wir nun den Aufruf von "dispatchEvent" hinzu:

Was ist das Problem bei diesem Ansatz? Jeder Code, der innerhalb von Listenern für das COMPLETE-Ereignis ausgeführt wird, wird ausgeführt, bevor die Methode closeData aufgerufen wird. Daher ändert sich der Status des Dispatchers innerhalb der Spanne der processDataChunk-Methode mehr als einmal und ist erst nach dem closeData-Aufruf "stabil". Dennoch sagen wir allen unseren Zuhörern, dass wir vor diesem Anruf fertig sind. Dies könnte zu einigen schwer aufzuspürenden Fehlern führen, bei denen ein Objekt behauptet, COMPLETE zu sein, es aber nicht ist. Die naheliegende Lösung besteht darin, einige Zeilen umzudrehen:


Schritt 6: Benutzerdefinierte Ereignisse

Sie sind bereit, Ihre eigenen Ereignisse zu versenden. Was sollten Sie nun versenden? Es gibt einige Optionen, die in Betracht gezogen werden sollten:

  1. Verwenden Sie einfach ein Ereignisobjekt und einen Ereignistyp, die bereits vom Flash Player bereitgestellt wurden
  2. Wiederverwendung eines vorhandenen Ereignisobjekts, aber Bereitstellung eines benutzerdefinierten Ereignistyps
  3. Eine bestehende Veranstaltung erneut versenden
  4. Erstellen Sie ein benutzerdefiniertes Ereignisobjekt
  5. Drücken vs. ziehen

Diese erste Option haben wir bereits in unseren vorherigen Beispielen gesehen. Wir müssen ein Ereignis absetzen, das sich auf den Abschluss eines Prozesses bezieht, und zufällig bietet Flash einen Ereignistyp (COMPLETE), der mit einem Ereignisobjekt (Event) verknüpft ist, das unseren Kriterien entspricht. Wir sind nicht verpflichtet, zusätzliche Daten mit der Veranstaltung zur Verfügung zu stellen. Das Aussenden eines Event.COMPLETE-Ereignisses ist alles, was wir brauchen.

Wir werden diese anderen Optionen in den nächsten Schritten untersuchen.


Schritt 7: Benutzerdefinierte Ereignistypen

Wie bereits im Schritt "Versand" angedeutet, handelt es sich bei Ereignistypen einfach um String-Folgenbezeichner. Sie können technisch gesehen jeder beliebige String sein. Normalerweise reicht es aus, daraus ein einzelnes Wort (wie "complete" oder "click") oder eine sehr kurze Phrase (wie "ioError" oder "keyFocusChange") zu machen; es muss nur innerhalb des Bereichs der verfügbaren Ereignisse eines bestimmten Ereignis-Dispatchers eindeutig sein.

Außerdem ist es Event-Objekten (einschließlich Unterklassen wie MouseEvent oder ProgressEvent) egal, welchen Ereignistyp sie bei der Instanziierung erhalten. Ein EventDispatcher sendet gerne Ereignisse von jedem Typbezeichner und jeder Klasse (sofern es die Event-Klasse oder eine Unterklasse ist).

Das Ergebnis davon ist, dass Sie Ihren eigenen Ereignistyp String erstellen, versenden und Listener damit einrichten können, und alles wird gut. Dies ist hilfreich, wenn Sie ein Ereignis auslösen möchten, aber nicht unbedingt eine gute Darstellung der Art des Ereignisses in den integrierten Klassen finden können.

Als Beispiel könnten Sie eine Klasse haben, die als Koordinator für mehrere Dinge gleichzeitig fungiert: XML laden, einige Bilder basierend auf den XML-Daten laden und ein Layout basierend auf den Größen der geladenen Bilder erstellen, bereit für eine erste Animation , an welcher Stelle Sie ein Ereignis versenden möchten. Während das COMPLETE-Ereignis geeignet sein könnte, können Sie das Gefühl haben, dass ein "bereites" Ereignis die Bedeutung angemessener kapselt.

Dies ist so einfach wie sich für den zu verwendenden String zu entscheiden und ihn dann zu verwenden. Verwenden Sie es sowohl beim Hinzufügen von Listenern als auch beim Versenden des Ereignisses. Wenn der String übereinstimmt, wird das Ereignis dorthin gelangen, wo es hin soll. Dies ist beispielsweise eine teilweise Auflistung einer hypothetischen Klasse:

Und Code von woanders im selben Programm:

Und das würde funktionieren.

Es ist jedoch erwähnenswert, dass es keine gute Praxis ist, überall übereinstimmende Strings einzugeben. Die Fehlerwahrscheinlichkeit ist hoch, und das Ereignissystem teilt Ihnen nicht mit, dass Sie "raedy" anstelle von "ready" eingegeben haben. Die Tatsache, dass das Ereignissystem flexibel und einfach zu bedienen ist - übergeben Sie ihm einfach einen beliebigen alten String für den Ereignistyp - ist auch eine Schwäche. Ihr Disponent akzeptiert gerne einen Listener für alles, auch für ein "raedy"-Ereignis. Es stimmt nicht wirklich ab, welche Ereignistypen mit welchen Ereignistypen tatsächlich gesendet werden.

Um dies zu verhindern, besteht der Standardansatz darin, den String, den Sie verwenden möchten, einfach irgendwo in eine statische Konstante einzufügen und diesen literalen String dann nie wieder zu verwenden. Verwenden Sie nur die Konstante. Natürlich ist die Möglichkeit von Tippfehlern nach wie vor groß, aber wenn Sie eine READY-Konstante und nicht das "ready"-Literal String verwenden, löst ein Tippfehler eine Compiler-Warnung aus. Sie können Ihren Fehler schnell und einfach beheben. Ein falscher Typ mit dem Literal Strings erzeugt weder einen Compilerfehler noch einen Laufzeitfehler. Das einzige, was passiert, ist, dass die SWF-Datei nicht richtig zu funktionieren scheint, weil der Ereignis-Listener nicht ausgelöst wird.

Aus diesem Grund werden diese Konstanten am häufigsten in der zugehörigen Event-Klasse gespeichert. In wenigen Schritten gelangen wir zu benutzerdefinierten Event-Klassen. Aber in der in diesem Schritt beschriebenen Situation (d. h. wir verwenden eine Event-Klasse wieder, aber keinen Ereignistyp), finde ich es bequemer, diese Konstante einfach in der Dispatcher-Klasse zu speichern. Wir könnten uns also dafür entscheiden, dies zu tun:

Und:

Dies gibt uns die Sicherheit, Ereignistypen in Konstanten zu speichern, ohne die Unannehmlichkeiten zu erzwingen, eine ganze Event-Klasse zu erstellen, die wir nicht benötigen. Ich muss betonen, dass dies eine stilistische Entscheidung ist, und Sie können diese Technik gerne verwenden oder nicht. Ich war der Meinung, dass es eine Erklärung rechtfertigt, damit Sie Ihre eigene informierte Entscheidung treffen können. In beiden Fällen sollten Sie Ihre benutzerdefinierten Ereignistyp-Strings auf jeden Fall in statischen Konstanten speichern. Wo diese statischen Konstanten definiert werden, liegt bei Ihnen.


Schritt 8: Erneutes Versenden von Ereignissen

Es gibt mehrere Fälle, in denen eine Klasse (nennen wir sie ClassX) eine Eigenschaft besitzt, die als eine andere Klasse typisiert ist (wir nennen sie ClassY), während sie selbst einer dritten Klasse gehört (wie wäre es mit ClassZ?). ClassX lauscht auf ein Ereignis von ClassY, aber wir möchten nicht nur, dass ClassX auf das Ereignis reagiert, wir möchten auch berücksichtigen, dass ClassX ein ähnliches (oder sogar dasselbe) Ereignis aussenden sollte, damit ClassZ auch weitere Maßnahmen ergreifen kann.

Als konkreteres Beispiel haben wir eine Klasse (dies wird "ClassX" sein), die eine Art Datenmanager ist. Es lädt ein XML-Dokument, analysiert es und speichert Daten aus dem XML in seinen eigenen Eigenschaften. Es hat also ein URLLoader-Objekt (dies wäre "ClassY") und wartet auf das Event.COMPLETE-Ereignis, wenn das XML-Dokument geladen wird.

Dann haben wir eine Hauptdokumentklasse, die den Datenmanager besitzt (die Dokumentklasse ist "ClassZ"). Es koordiniert das Laden der Daten mit anderen UI-Elementen, möchte also wissen, wann die Daten geladen und bereit sind, damit es UI-Elemente basierend auf den Daten erstellen und gestalten kann.

Wir könnten dies tun:

Aber wir könnten auch dies tun:

Hier versenden wir einfach die bestehende Veranstaltung neu. Wir verwenden nicht nur den Ereignistyp und die Event-Klasse wieder, sondern verwenden tatsächlich das gesamte Event-Objekt, wie es an unseren eigenen Listener übergeben wurde.

Es ist keine Raketenwissenschaft, aber es ist eine praktische kleine Technik, die überraschenderweise nicht so offensichtlich ist.

"Aber warten Sie", müssen Sie denken, "wenn wir ein Ereignis, das vom URLLoader-Objekt stammt, erneut versenden würden, wäre das target des Ereignisses dann nicht immer noch _xmlLoader, wenn es wieder in die Dokumentenklasse zurückkehrt?" Und Sie hätten einen sehr guten und nachdenklichen Punkt, und ich wäre stolz auf Sie, dass Sie so fleißig nachdenken, aber Sie würden sich irren.

Beim Redispatching von Ereignissen passiert etwas Magisches. Die target-Eigenschaft wird auf den aktuellen Dispatcher festgelegt. Ein funktionierendes Beispiel für den Code in diesem Schritt finden Sie im Downloadpaket mit dem Titel redispatch.

Eigentlich ist es gar nicht so magisch. Wenn beim Aufrufen von "dispatchEvent" das übergebene Event-Objekt bereits ein target hat, wird die clone-Methode für das Event aufgerufen, wodurch eine identische, aber diskrete Kopie des ursprünglichen Event erstellt wird, mit Ausnahme des in target enthaltenen Werts.


Schritt 9: Benutzerdefinierte Ereignisobjekte

Alles, was bisher erwähnt wurde, ist etwas, das Sie wissen wollen. Aber es wird einen Punkt geben, an dem es am besten ist, Ihr eigenes benutzerdefiniertes Ereignis zu versenden. Nicht nur ein benutzerdefinierter Ereignistyp, sondern eine ganze benutzerdefinierte Event-Klasse.

Der Prozess dafür ist einfach, Sie müssen nur ein paar Schritte befolgen. Wir werden diese zu gegebener Zeit besprechen. Beachten Sie, dass ein Großteil davon Boilerplate-Code ist, und Sie könnten leicht eine Vorlage für eine Event-Unterklasse erstellen und nur ein paar Schlüsselelemente ändern und loslegen. Die allgemeinen Schritte in verkürzter-als-ob-du-wussten-wovon-ich-sprach:

  1. Unterklasse-Event
  2. Rufen Sie super(...)
  3. Ereignistypen in öffentlichen statischen Konstanten speichern
  4. Deklarieren Sie private Eigenschaften, um benutzerdefinierte Daten zu speichern
  5. Erstellen Sie öffentliche Getter, um schreibgeschützten Zugriff auf die benutzerdefinierten Informationen zu ermöglichen
  6. (Optional) Überschreiben Sie die clone-Methode
  7. (Optional) Überschreiben Sie die toString-Methode

Um diesen Prozess genauer zu erklären, beginnen wir mit unserem Slider-Projekt und erstellen das SliderEvent, das wir dafür benötigen. Wir müssen also unser Projekt starten, bevor wir etwas Code schreiben können, also eine kurze Umleitung im nächsten Schritt, dann beginnen wir mit dem Schreiben einer benutzerdefinierten Event-Klasse.


Schritt 10: Erstellen Sie die Projektstruktur

Wir halten die Dinge hier ziemlich einfach, aber wir werden trotzdem Pakete für unsere Klassen erstellen.

Erstellen Sie zunächst einen Ordner für das gesamte Projekt. Meins wird Slider heißen.

Erstellen Sie darin einen com-Ordner und darin einen activetuts-Ordner.

Erstellen Sie nun zwei Ordner innerhalb von activetuts: events und ui. Ihre endgültige Ordnerstruktur sollte in etwa so aussehen:

  • slider
    • com
      • activetuts
        • events
        • slider

Nun zurück zu unserer Event-Klasse.


Schritt 11: Event-Unterklassen

Erstellen Sie zunächst eine neue Textdatei im Ordner slider/com/activetuts/events und nennen Sie sie SliderEvent.as. Wir werden zuerst die Boilerplate für jede Klasse einfügen:

Hier sollte es nichts Überraschendes geben, und wenn Sie ActionScript-Vorlagen für Ihren Texteditor haben, sollten Sie nicht einmal so viel eingeben müssen.

Jetzt ändern wir dies so, dass es Event erweitert.

Wie Sie sehen, importieren wir einfach die Event-Klasse, fügen Sie extends Event zur Klassendefinition hinzu.


Schritt 12: super anrufen

Unsere Superklasse kann viel für uns erledigen, was großartig ist, aber wir müssen sicherstellen, dass wir die Superklasse richtig initialisieren, wenn wir unsere Unterklasse initialisieren. Wir müssen den Konstruktor mit Argumenten einrichten, die denen im Konstruktor von Event entsprechen, und diese zusammen mit einem Aufruf an super übergeben.

Dies sind bisher grundlegende Unterklassentechniken. Abhängig von den Fähigkeiten Ihres Editors mit Vorlagen können Sie sogar eine Superklasse angeben, wenn Sie die Datei erstellen, und dies alles für Sie erledigen lassen. Flash Builder ist zum Beispiel in der Lage, dies zu tun.


Schritt 13: Speichern Sie Ereignistypen in öffentlichen statischen Konstanten

Vermutlich sind dieser Ereignisklasse ein oder mehrere Ereignistypen zugeordnet. Genauso wie das COMPLETE-Ereignis der Event-Klasse und das CLICK sogar der MouseEvent-Klasse zugeordnet ist, wird unsere benutzerdefinierte Ereignisklasse wahrscheinlich benutzerdefinierte Ereignistypen haben.

Dies ist so einfach wie das Schreiben einer Zeile wie der folgenden für jeden Ereignistyp, den Sie hinzufügen möchten:

Machen wir das jetzt für die SliderEvent-Klasse.

Wir könnten unsere Klasse jetzt theoretisch gebrauchen. Wir können das SliderEvent in dispatchEvent verwenden und Ereignisse mit dem SliderEvent.CHANGE-Ereignistyp abhören und erstellen.

Aber wir werden hier nicht aufhören. Es gibt mehr zu beachten. Aber bevor wir mehr Code schreiben, müssen wir noch einen Abstecher in die Theorie machen.


Schritt 14: Push vs. Pull

Wenn ein Ereignis ausgelöst wird, reicht es manchmal aus, einfach zu wissen, dass das Ereignis eingetreten ist. Wenn Sie beispielsweise an Event.ENTER_FRAME-, Event.COMPLETE- oder TimeEvent.TIMER-Ereignissen interessiert sind, möchten Sie wahrscheinlich nur wissen, dass das Ereignis stattgefunden hat. Es gibt jedoch andere Zeiten, in denen Sie wahrscheinlich mehr wissen möchten. Beim Anhören von MouseEvent.CLICK interessiert Sie möglicherweise, ob die Umschalttaste gedrückt gehalten wurde, oder die Koordinaten der Maus zum Zeitpunkt des Klickens. Wenn Sie sich ProgressEvent.PROGRESS anhören, möchten Sie wahrscheinlich den tatsächlichen Fortschritt des Ladevorgangs wissen. das heißt, wie viele Bytes geladen wurden und wie viele insgesamt geladen werden sollen.

Der Unterschied zwischen diesen beiden Methoden wird manchmal als "Push" und "Pull" bezeichnet. Diese Begriffe beziehen sich darauf, wie der Ereignis-Listener Daten in Bezug auf das Ereignis abruft. Wenn die Daten "gepusht" werden, werden Daten im Ereignisobjekt gespeichert, und um die Daten abzurufen, muss der Listener lediglich Eigenschaften des Ereignisobjekts verwenden. Sollen jedoch Daten "gezogen" werden, enthält das Event-Objekt in der Regel nur sehr wenige Informationen - nur das Nötigste: den Typ, das Ziel usw. Dieses Ziel ist jedoch unverzichtbar, da es den Zugriff auf den Event-Dispatcher ermöglicht an den Ereignis-Listener, sodass der Listener die benötigten Daten vom Dispatcher abrufen kann.

Mit anderen Worten, Sie können entweder eine Reihe von Daten an den Listener innerhalb des Ereignisobjekts pushen oder den Listener auffordern, die Daten nach Bedarf aus dem Dispatcher zu ziehen.

Die Vor- und Nachteile der einzelnen Techniken sind meiner Meinung nach etwas ausgewogen und der Weg, den Sie für Ihr Veranstaltungsobjekt wählen, hängt von der jeweiligen Situation und nicht von persönlichen Vorlieben ab.

Ausstellung A:

Vorteile Nachteile
Drücken
  • Daten sind im Ereignisobjekt leicht zugänglich
  • Möglicherweise übertragen Sie nicht benötigte Daten. Das Aufblähen des Ereignisobjekts mit einer Menge Daten, die selten verwendet werden, kann zu Speicher- und/oder Leistungsproblemen führen.
Ziehen
  • Sehr einfach zu schreiben. Sie benötigen wahrscheinlich keine benutzerdefinierte Event-Klasse, um ein Pull-Ereignis auszuführen.
  • Sehr einfach zu bedienen. Wenn es sich nur um eine Event-Klasse handelt, ist das einzige erforderliche Argument der Ereignistyp.
  • Wenn Daten, die normalerweise aus dem Dispatcher gezogen werden, teuer zu berechnen und zurückzugeben sind, können Sie die Leistung beeinträchtigen, indem Sie vom Dispatcher verlangen, diese Informationen ständig weiterzugeben.
  • Einige Daten sind möglicherweise schwer abzurufen, z. Das KeyboardEvent verfügt über eine keyCode-Eigenschaft, um die Taste anzugeben, die zum Auslösen des Ereignisses gedrückt wurde.

Dies könnte eine gute Diskussion für die Kommentare sein; Ich bin sicher, dass viele von Ihnen, die lesen, eine leidenschaftliche Meinung darüber haben, welche Methode die bessere ist. Persönlich versuche ich, die Methode zu finden, die für die Situation am besten funktioniert.

Trotzdem ist es erwähnenswert, dass unsere SliderEvent-Klasse bis jetzt eher "Pull-ish" ist. Zur Veranschaulichung und weil es keine schlechte Idee ist (obwohl ich mir einige davon ausgedacht habe), werden wir dies zu einem Ereignis machen, das Daten mit sich bringt. nämlich der Wert des Schiebereglers, wenn er geändert wurde.


Schritt 15: Deklarieren privater Eigenschaften zum Enthalten benutzerdefinierter Daten

Um ein Push-Ereignis zu implementieren, benötigen wir einen Ort zum Speichern der gepushten Daten. Zu diesem Zweck fügen wir eine private Eigenschaft hinzu.

Sie sollten SliderEvent immer noch geöffnet haben (wenn nicht... worauf warten Sie noch?). Fügen Sie die markierte Zeile hinzu:

Als nächstes ändern wir den Konstruktor so, dass wir einen Wertparameter akzeptieren können, und legen die private Eigenschaft damit fest:

Auf diese Weise können wir das SliderEvent einfach erstellen und seine Push-Daten in einer Zeile einrichten.

Warum private Immobilien nutzen? In diesem Fall möchten wir die Daten schützen. Meiner Meinung nach sind die Daten zu einem Ereignis unveränderlich, solange sie mit dem Ereignis verknüpft sind. In der Lage zu sein, die Daten eines Ereignisobjekts zu ändern, ist wie das Bearbeiten eines Geschichtslehrbuchs. Um fair zu sein, dies ist meine Meinung und der von Adobe mit seinen integrierten Klassen verwendete Standard besteht darin, beschreibbare Eigenschaften zu verwenden (technisch gesehen verwenden sie private Eigenschaften und öffentliche Getter und Setter, aber das Endergebnis ist das gleiche).


Schritt 16: Erstellen Sie öffentliche Getter für die benutzerdefinierten Daten

Der nächste Schritt wäre also, sicherzustellen, dass wir auf die übertragenen Daten zugreifen können. Ein privates Eigentum allein ist für diesen Zweck nicht nützlich. Daher müssen wir einen öffentlichen Getter für die Eigenschaft _sliderValue schreiben. Wir werden uns dafür entscheiden, keinen Setter zu schreiben, damit die Eigenschaft schreibgeschützt wird (wie im letzten Schritt besprochen).

Fügen Sie diese Methode der Klasse hinzu:

Dadurch wird ein Getter hinzugefügt, sodass wir auf den sliderValue auf eine Eigenschafts-ähnliche Weise zugreifen können. Ich entscheide mich, den passenden Setter nicht hinzuzufügen. Sie können einen hinzufügen, wenn Sie der Meinung sind, dass es sich lohnt.


Schritt 17: Überschreiben Sie die clone-Methode

Ich habe vor einiger Zeit die clone-Methode erwähnt. Sie werden wahrscheinlich selbst nicht oft clone, aber es ist keine schlechte Idee, die clone-Methode zu überschreiben, damit Ihr benutzerdefiniertes Ereignis gut mit dem Ereignissystem zusammenspielt.

Fügen Sie diese Methode zu Ihrer Klasse hinzu:

Beachten Sie zunächst die Signatur dieser Methode. Wir verwenden override, weil diese Methode in Event deklariert ist und wir sie erben. Es gibt auch ein Objekt vom Typ Event zurück. Stellen Sie beim Schreiben Ihrer clone-Uberschreibung sicher, dass Sie den richtigen Rückgabetyp eingeben. Es ist leicht zu vergessen und den Typ Ihrer Klasse dort einzufügen, aber das führt zu einem inkompatiblen Überschreibungsfehler, da die Rückgabetypen übereinstimmen müssen.

Alles, was wir im Kern des Events wirklich tun, ist, ein neues SliderEvent zu erstellen und die gleichen Werte zu übergeben, die wir im aktuellen Event-Objekt gespeichert haben. Dadurch entsteht eine identische, aber diskrete Kopie: ein Klon.

Dies ist ein optionaler Schritt, aber es ist ein schneller Erfolg und stellt sicher, dass Ihr benutzerdefiniertes Event gut mit dem Rest des Eventsystems zusammenspielt.


Schritt 18: Überschreiben Sie die toString-Methode

Eine letzte Sache, und auch dies ist optional. Aber es ist auch als Debug-Tool sehr nützlich, so dass es sich normalerweise innerhalb weniger Anwendungen bezahlt macht.

Falls Sie es noch nicht erfahren haben, die toString-Methode existiert auf allen Object (sie ist in Object deklariert und definiert, der Überklasse, von der alle anderen Klassen erben, ob Sie es wollen oder nicht). Es kann explizit aufgerufen werden, aber das Praktische ist, dass es in einigen Fällen automatisch aufgerufen wird. Wenn Sie beispielsweise object an die Trace-Funktion übergeben, muss für jedes Objekt, das noch kein String ist, toString aufgerufen werden, um sicherzustellen, dass es für das Ausgabebedienfeld gut formatiert ist. Es wird sogar aufgerufen, wenn mit Objekten zusammen mit Strings gearbeitet wird, wie bei der Verkettung. Wenn Sie zum Beispiel dies schreiben:

ActionScript ist intelligent genug, um 42 in eine String-Darstellung der Number umzuwandeln, bevor der String verkettet wird. Der Versuch, einen String und eine Number hinzuzufügen, ist eine schlechte Nachricht, aber das Konvertieren einer Number in einen String und das anschließende Verketten mit einem anderen String ist in Ordnung.

Wenn Sie also Ihre eigenen Klassen schreiben, können Sie eine toString-Methode bereitstellen, die keine Argumente akzeptiert und einen String zurückgibt, und einen beliebigen String zurückgeben.

Im Fall von Events-Ebjekten bietet Adobe hilfreicherweise eine formatToString-Methode, damit alle Event bei der Verfolgung ähnlich aussehen. Wir verwenden es in der Methode, die wir unserer Klasse hinzufügen werden:

Notieren Sie sich zunächst die Methodensignatur. Auch hier handelt es sich um eine override, sodass wir dieses Schlüsselwort haben. Es ist public, nimmt keine Parameter an und gibt einen String zurück (was offensichtlich sein sollte).

Beachten Sie als Nächstes die einzelne Zeile im Methodenrumpf. Wir rufen formatToString auf, das in Event definiert ist, damit es einfach zu verwenden ist. Das erste Argument, das wir ihm übergeben, ist der String-Name der Klasse. Danach sind die Argumente offen. Sie können eine, 15 oder keine abgeben. Wir gehen in zwei durch. Egal wie viele Sie übergeben, sie sollten alle Strings sein und mit den Eigenschaftsnamen Ihrer Klasse übereinstimmen. "type" wird von Event definiert, aber "sliderValue" wird von unserer eigenen Klasse definiert. In jedem Fall wird der Name der Eigenschaft ausgegeben, gefolgt von einem Gleichheitszeichen, gefolgt vom tatsächlichen Wert dieser Eigenschaft. Kurz gesagt, es wird am Ende so aussehen:

Dies ist völlig funktionslos, aber sehr nützlich. Es kann einen schnellen Einblick in das Ereignis geben, wenn die Dinge nicht so funktionieren, wie Sie es sich vorstellen.


Schritt 19: Erstellen des Sliders

An dieser Stelle haben wir das Schlüsselkonzept dieses Tutorials durchgearbeitet: das Schreiben einer benutzerdefinierten Event-Klasse. Aber wir müssen es wirklich auf die Probe stellen. Wir werden den Rest unserer Zeit damit verbringen, die einfache Slider-Anwendung zu erstellen, die zu Beginn des Tutorials in der Vorschau angezeigt wurde.

Wir haben bereits eine Projektordnerstruktur; Wir brauchen nur noch ein paar Dateien. Wir beginnen mit der FLA-Datei.

Erstellen Sie eine neue Flash-Datei (natürlich ActionScript 3.0) und speichern Sie sie als ActiveSlider.fla im Stammverzeichnis Ihres Projektordners. Ich gehe davon aus, dass Sie keine Schritt-für-Schritt-Anleitungen benötigen, um diese einfache FLA zusammenzustellen, sondern ich werde die Schlüsselelemente darstellen. Sie können auch die FLA-Datei im start-Ordner des Downloadpakets als Referenz verwenden oder diese FLA einfach in Ihren Projektordner kopieren und diesen Schritt als erledigt bezeichnen.

Es gibt drei Hauptobjekte auf der Bühne.

  1. Die Slider-Spur. Dies ist ein langer, schmaler Streifen, der anzeigt, wohin der Schieberegler verschoben werden kann. Der Slider bewegt sich "in" der Spur.
    • Muss ein Filmclip sein
    • Für die einfachste Mathematik sollte die Grafik so angeordnet sein, dass sich der Registrierungspunkt in der oberen linken Ecke befindet
    • Nennen Sie es track_mc
    • In die obere Mitte legen; es sollte den größten Teil der Bühnenbreite einnehmen und Platz darunter haben.
  2. Der Rutschengriff. Dies ist ein schaltflächengroßes Element, das die aktuelle Position des Schiebereglers anzeigt. Es ist das Stück, das sich entlang der Strecke bewegt und auf die Maus reagiert.
    • Muss ein Filmclip sein.
    • Auch für Mathe sollte der Registrierungspunkt oben links sein
    • Nennen Sie es grip_mc
    • Platzieren Sie es über der Schiene, so dass es vertikal mit der Schiene zentriert ist und irgendwo am linken und rechten Ende der Schiene liegt
    • Es sollte oben auf der Schiene gestapelt werden, damit der Griff die Schiene verdeckt (auf eine höhere Schicht legen)
  3. Das Ausgabefeld. Dies ist ein Textfeld, das zu unseren eigenen Demonstrationszwecken den aktuellen Wert des Schiebereglers anzeigt.
    • Muss ein dynamisches Textfeld sein.
    • Nennen Sie es output_tf
    • Schriftarten sind belanglos; Stellen Sie es nach Belieben ein und betten Sie es nach Bedarf ein
    • Platzieren Sie es im unteren Bereich der Bühne, damit es nicht mit dem Platzbedarf des Schiebereglers kollidiert.
The stage of our FLAThe stage of our FLAThe stage of our FLA

Abgesehen vom Anschließen der Dokumentenklasse, die wir in zwei Schritten schreiben werden, ist die FLA einsatzbereit.


Schritt 20: Die ActiveSlider-Klasse

Die wichtigste UI-Klasse, mit der wir arbeiten werden, ist die ActiveSlider-Klasse. Dadurch wird EventDispatcher erweitert, die beiden Movieclips auf der Bühne als Ziel festgelegt und die Mausinteraktivität für das Schiebereglerverhalten eingerichtet. Am aufregendsten ist, dass es ein SliderEvent auslöst.

Erstellen Sie zunächst eine neue Klassendatei namens ActiveSlider.as im Ordner com/activetuts/slider Ihres Projekts. Diese Klasse ist nicht zu intensiv (zumindest nicht für unsere Zwecke hier. Eine Slider-Klasse könnte viel mehr in Anspruch nehmen), und ich werde den Code einfach vollständig präsentieren und im Laufe der Zeit diskutieren:

Nichts Aufregendes, nur das Paket einrichten und importieren.

Wir brauchen diese drei Eigenschaften. Die ersten beiden verfolgen die Sprite (oder MovieClip), aus denen der Schieberegler besteht. Der dritte wird beim Ziehen des Schiebereglergriffs verwendet; es hilft, die Position des Griffs von der Maus um einen Betrag relativ zu der Stelle zu halten, an der der Griff zuerst geklickt wurde.

Dies ist der Konstruktor. Es akzeptiert zwei Sprite-Argumente, die zur Speicherung an die ersten beiden dieser Eigenschaften weitergegeben werden. Es führt dann eine einfache Überprüfung durch, um sicherzustellen, dass sich die beiden Sprite im selben Koordinatenraum befinden, indem überprüft wird, dass ihre parent Eigenschaften auf dasselbe Objekt verweisen. Wenn dies nicht der Fall ist, ist unsere Berechnung für die Platzierung des Griffs möglicherweise unzuverlässig, sodass wir einen Fehler ausgeben, um den Entwickler zu warnen. Der Rest des Konstruktors dient dem Hinzufügen von zwei Ereignis-Listenern. Das erste ist ein MOUSE_DOWN-Ereignis und geradeaus. Die zweite versucht jedoch, der stage ein MOUSE_UP-Ereignis hinzuzufügen, das möglicherweise vorhanden ist oder nicht, je nachdem, ob sich das grid-Sprite in der Anzeigeliste befindet oder nicht. Die nächsten beiden Methoden könnten dies etwas klarer machen:

Die Methode onAddedToStage ist ein Ereignis-Listener für das Ereignis ADDED_TO_STAGE, das im Konstruktor eingerichtet wurde, jedoch nur, wenn das Sprite-Sprite nicht bereits einen Verweis auf die stage hatte. Die Methode addStageListener fügt der stage einfach den Ereignis-Listener MOUSE_UP hinzu. Wenn also im Konstruktor eine stage-Referenz vorhanden ist, rufen wir addStageListener direkt auf. Wenn keine stage-Referenz vorhanden ist, richten wir das Ereignis ADDED_TO_STAGE ein, und wenn der Griff zur Anzeigeliste hinzugefügt wird und somit eine stage-Referenz hat, wird die Methode onAddedToStage ausgelöst, die dann wiederum addStageListener aufruft. Es entfernt auch den Ereignis-Listener ADDED_TO_STAGE, da wir dies nur einmal tun müssen.

Als nächstes haben wir unsere beiden Maus-Ereignis-Listener. In onDown besteht die Schlüsselzeile darin, dann einen ENTER_FRAME-Ereignis-Listener hinzuzufügen. In onUp entfernen wir diesen Listener. Auch in onDown notieren wir, wo auf dem Griff der Mausklick tatsächlich stattgefunden hat, und speichern dies in _grabOffset. Dies wird als nächstes in unsere onFrame-Methode einfließen.

Dies ist der Kern unserer Slider-Logik. Diese Methode wird bei einem ENTER_FRAME-Ereignis wiederholt ausgelöst, jedoch nur, wenn die Maus auf den Griff gedrückt wurde, und nur so lange, wie die Maus gedrückt bleibt.

Zuerst stellen wir die x-Eigenschaft des Griffs so ein, dass sie mit der Mausposition übereinstimmt, wir müssen ihn nur basierend auf der ursprünglichen Mausposition versetzen, damit er sich reibungslos bewegt und nicht springt, sodass sich seine linke Kante an der Maus befindet.

Die nächsten beiden Zeilen berechnen die umgrenzenden Rechtecke der Griff- und Spur-Sprite. Wir werden diese Rechtecke in der kommenden Mathematik verwenden, also halten wir die Dinge aufgeräumter, indem wir die Rechtecke im Voraus berechnen und in Variablen speichern.

Dann gibt es den if-Block. Dies beschränkt unseren Schieberegler nur auf die Spur. Es ist eine einfache Überprüfung, ob das x des Griffs, wie in der ersten Zeile der Methode berechnet, niedriger ist als das x der Spur (links davon). Wenn dies der Fall ist, wäre es zu weit, daher müssen wir den Griff auf diesen Mindestwert verschieben. In ähnlicher Weise prüfen wir, ob die rechte Kante des Griffs größer ist als (rechts davon) die rechte Kante der Spur, und wenn ja, müssen wir sie auf diesen maximalen Wert zurückspulen.

Endlich haben wir eine zuverlässige Griffposition, und vorerst verfolgen wir nur den aktuellen Schiebereglerwert, der im letzten Code für die Klasse berechnet wird:

Dies ist ein einfacher Getter, obwohl die für den Rückgabewert verwendete Mathematik etwas verwirrend sein kann. Er bestimmt die aktuelle Griffposition als Prozentsatz des Bewegungsbereichs des Griffs. Es wäre offensichtlicher, wenn es nur so wäre:

...was vernünftig ist, aber nicht berücksichtigt, dass der Grip nicht wirklich die gesamte Breite der Strecke abdeckt. Es geht bis zum linken Rand, aber nur bis zum rechten Rand der Spur abzüglich der Breite des Griffs. Das ist also genauer:

Dies macht die Breite, um die wir den Bewegungsumfang teilen. Es kann jedoch immer noch ein Gotcha sein, dass die Spur von ihrem Container nach links oder rechts versetzt werden kann, was bedeutet, dass die Werte, die wir erhalten, nicht ganz richtig sind. Wir müssen das neutralisieren, indem wir die x-Position der Spur vom x des Grips subtrahieren, und wir enden mit Folgendem:

Als Referenz ist hier die komplette Klasse, wobei meine Wanderungen weggelassen wurden:

Wir haben unsere SliderEvent-Klasse noch nicht hinzugefügt. Wir werden einen separaten Schritt unternehmen, um das zu tun. Aber zuerst benötigen wir unsere Dokumentklasse, damit wir den ActiveSlider tatsächlich verwenden können.


Schritt 21: Die Document-Klasse

Wir benötigen eine weitere Datei, damit es funktioniert: unsere Dokumentklasse. Erstellen Sie eine neue Klassendatei mit dem Namen SliderDemo im Projektstammordner. Fügen Sie den folgenden Code hinzu:

Dies ist viel einfacher als unsere ActiveSlider-Klasse. Es richtet wirklich nur einen ActiveSlider in die Eigenschaft namens _slider ein.

Gehen Sie zurück zur FLA-Datei und geben Sie SliderDemo in das Dokumentklassenfeld ein, und Sie sollten dies ausprobieren können. Der Schieberegler sollte in der Lage sein, sich hin und her zu bewegen und sich auf die Breite der Spur zu beschränken.

Nun zu einer letzten Aufgabe. Wir müssen ein SliderEvent.CHANGE-Ereignis aussenden und darauf warten. Wir werden das als nächstes tun.


Schritt 22: Dispatching des SliderEvent

Kehren Sie zur ActiveSlider-Klasse zurück, und nehmen Sie eine einzeilige Änderung an der onFrame-Methode vor:

Wir haben die Ablaufverfolgung entfernt und durch eine echte Live-Ereignissendung ersetzt. Damit dies funktioniert, müssen wir jedoch die SliderEvent-Klasse importieren:


Schritt 23: Warten auf das SliderEvent

Kehren Sie schließlich zur SliderDemo-Klasse zurück, und ändern Sie sie so, dass sie auf das SliderEvent wartet und darauf reagiert:

Wir importieren erneut die SliderEvent-Klasse, und nachdem wir den ActiveSlider erstellt haben, fügen wir dem Schieberegler einen Listener namens onSliderChange hinzu. Diese Methode ist die größte Ergänzung, aber immer noch ein regelmäßiger Ereignis-Listener. Es ist ähnlich wie bei jedem anderen Ereignislistener, nur stellen wir sicher, dass wir das Ereignisargument als SliderEvent eingeben, denn das ist es, was wir bekommen.

Die erste Codezeile ist etwas überflüssig, aber ich wollte sehen, was passiert, wenn Sie unser SliderEvent-Objekt verfolgen. Wenn Sie dies ausführen, sehen Sie eine für Flash typische Formatierung des Ereignisobjekts.

The event object represented as a StringThe event object represented as a StringThe event object represented as a String

Die zweite Zeile macht das, wonach wir anfangs gesucht haben. Es greift einfach die sliderValue-Eigenschaft ab, wandelt sie in einen String um und klebt diesen String dann in das TextField auf der Bühne, damit wir den Schiebereglerwert im Film sehen können.


Step 24: Wrapping Up

Wenn Sie mit dem Rollout Ihrer eigenen benutzerdefinierten Ereignisse beginnen, beginnen Sie mit ActionScript 3 so zu arbeiten, wie es verwendet werden sollte. Ereignisse helfen Ihnen, Klassen voneinander zu entkoppeln, und ein gut strukturierter Ereignisfluss in Ihrer Anwendung kann wirklich den Unterschied zwischen etwas, mit dem man einfach arbeiten kann, und etwas, das fehlerhaft und temperamentvoll ist, ausmachen. Mit diesem (theoretisch) letzten Teil von AS3 101 solltest du auf dem richtigen Weg sein, ein Ninja zu werden.

Danke fürs Lesen, und ich sehe dich wieder hier auf Activetuts+, bevor du es weißt!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Scroll to top
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.