Ereignisse werden mit Listenern überwacht und ausgeführt. Unnötig zu sagen, dass das Thema wichtig ist. In AS3 kann man eine Aktion nicht mehr direkt einer Schaltfläche oder einem MC zuweisen, indem man ihn anklickt und dann im Aktionenfenster die Aktion einträgt. Auch die alten Events wurden durch Event.Listener ersetzt. Dieses Thema in den
Über die Event Phasen Variable kann man ermitteln, in welcher Phase sich der Event Flow befindet. Diese Überprüfung sollte nicht über die integer Werte erfolgen sondern über die Konstanten.
import flash.events.MouseEvent; var tT:TextField = new TextField(); tT.text = "Textfeld Text"; tT.autoSize = TextFieldAutoSize.LEFT; stage.addChild (tT); stage.addEventListener (MouseEvent.CLICK, clickListener, true); stage.addEventListener (MouseEvent.CLICK, clickListener, false); function clickListener (evt:MouseEvent):void { var phase:String; switch (evt.eventPhase) { case EventPhase.CAPTURING_PHASE: phase = "Capture"; break; case EventPhase.AT_TARGET: phase = "Target"; break; case EventPhase.BUBBLING_PHASE: phase = "Bubbling"; break; } trace("die aktuelle Phase ist "+phase); }
Wenn die Event Phasen Variable die Phase AT_TARGET anzeigt, wird der Event an das Objekt versand auf dass es registriert ist. So kann man sicherstellen, dass Ereignisse, die auf die Abkömmlinge zielen, ignoriert werden.
Nehmen wir mal an wir hätten auf der Bühne viele Input Objekte wie Texteingabefelder, Buttons etc. und möchten dass ein MouseEvent.CLICK nur ausgeführt wird wenn man auf eine leere Stelle der Bühne klickt. Dann könnte man den Event auf die Bühne registrieren und über die Event Phasen Variable auf AT_TARGET überprüfen.
stage.addEventListener (MouseEvent.CLICK, clickListener); function clickListener (evt:MouseEvent):void { if (evt.eventPhase == EventPhase.AT_TARGET) { trace ("die leere Bühne wurde angeklickt."); } }
Das funktioniert auch anders rum, so dass der Code nur ausgeführt wird, wenn ein Objekt oder Abkömmling (child) angeklickt wird, jedoch nicht, wenn auf eine leere Stelle geklickt wird.
Man kann während des Event Flows den Event Dispatch stoppen. Das nennt man "consuming an event". Damit übergeht man die normale Ausführung der Events. Für diesen Zweck gibt es 2 Anweisungen:
stopImmediatePropagation() stoppt den Event Dispatch sofort und lässt nicht zu, dass eventuell anstehende Event Listener ausgeführt werden.
stopPropargation() stoppt den Event Dispatch nachdem die anstehenden Event Listener ausgelöst worden sind.
dazu ein Beispiel:
var tS:Sprite = new Sprite(); var tT:TextField = new TextField(); tT.text = "Klicke hier"; tT.autoSize = TextFieldAutoSize.LEFT; tS.addChild (tT); addChild (tS); tS.addEventListener (MouseEvent.CLICK, containerClickListenerOne, true); tS.addEventListener (MouseEvent.CLICK, containerClickListenerTwo, true); tT.addEventListener (MouseEvent.CLICK, childClickListner, false); function containerClickListenerOne (evt:MouseEvent):void { //halte die anderen beiden events davon ab, ausgeführt zu werden evt.stopImmediatePropagation (); trace ("containerClickListenerOne"); } function containerClickListenerTwo (evt:MouseEvent):void { trace ("containerClickListenerTwo"); } function childClickListner (evt:MouseEvent):void { trace ("childClickListener"); }
Beachte, die Reihenfolge, in der die EventListener hinzugefügt wurden, da sie auch in der Reihenfolge ausgeführt werden.
Ohne die stopImmediatePropargation() - Anweisung würde beim Click auf das Child Objekt tT der Event 3 mal ausgelöst. 2 mal während der Capture Phase und einmal während der Target Phase. Durch stopImmediatePropargation() wird der Event nur einmal ausgelöst und zwar durch containerClickListenerOne()
Würde man stattdessen stopPropargation() einfügen, würde der Event Listener 2 mal ausgelöst, wenn man auf das Child Objekt klickt und zwar würde die Funktion childClickListenerTwo ausgeführt, aber childClickListener nicht.
Nehmen wir mal an wir hätten eine Menue.as Klasse in der sich ein paar Menüpunkte befinden. Die Menüpunkte sind in diesem Beispiel Movieclip-Klassen, welche in der Bibliothek der fla liegen. Der Klassennamen ist "But".
In der Menue.as Klasse gibt es eine boolsche Variable "activate". Ist ihr Wert false, sollen die Menüpunkte (die Instanzen von "But") deaktiviert werden, soll heißen die Anweisungen/ Event Listener die darauf verweisen, sollen nicht ausgeführt werden.
Los gehts, die Klasse Menue.as
package { import flash.display.Sprite; import flash.events.*; public class Menue extends Sprite { public var activate:Boolean; public function Menue () { // constructor code activate = false; //But ist ein Display Object, beispielsweise eine MovieClip Klasse var tool1:But= new But(); var tool2:But= new But(); var tool3:But= new But(); tool2.y = tool1.height + 10; tool3.y = tool2.y + tool2.height + 10; addChild (tool1); addChild (tool2); addChild (tool3); addEventListener (MouseEvent.CLICK, clickListener, true); addEventListener (MouseEvent.CLICK, clickListenerTwo, true); } private function clickListener (evt:MouseEvent):void { if (! activate) { evt.stopImmediatePropagation (); } } private function clickListenerTwo (evt:MouseEvent):void { trace (evt.target.name); } } }
In der fla Datei (siehe folgenden Code) wird eine Instanz der Menue.as Klasse erstellt. Außerdem kann man die public Variable "activate" auf true oder false setzen um das Verhalten der Menuepunkte zu steuern.
var tP:Menue = new Menue(); addChild(tP); tP.activate=true;
Denkbar wäre auch folgende Einsatzmöglichkeit in Spielen.
Es gibt eine Klasse gameManager.as und darin enthalten lauter child-raketen-display Objekte, welche das Schiff treffen können und diesem dann Schaden zufügen. Das wird über einen Event dispatch der auf die child-raketen registriert ist, geregelt. Wenn nun das Schiff im Modus "unverwundbar" ist kann man mit stopPropargation alle Zerstörungsaktionen seitens der child-raketen unterbinden.
preventDefault() bricht das Standardverhalten eines Ereignisses ab, wenn das Ereignis abgebrochen werden kann. Siehe folgendes Beispiel mit einem Texteingabefeld.
Mit diesen beiden Events kann man darauf reagieren, ob der Flashplayer den Systemfocus hat oder nicht. Das ist für den Standalone Player gedacht.
import flash.events.Event; import flash.utils.Timer; //timer erzeugen und Funktion, die eine MC Instanz namens 'rad' dreht var timer:Timer = new Timer(50,0); timer.addEventListener (TimerEvent.TIMER, timerUpdate); function timerUpdate (event:TimerEvent):void { rad.rotation += 4; } //Registrierung, um benachrichtigt zu werden, //wenn der Flashplayer den Focus erhält oder verliert addEventListener (Event.ACTIVATE, aktivL); addEventListener (Event.DEACTIVATE, deaktivL); function aktivL (evt:Event):void { timer.start (); } function deaktivL (evt:Event):void { timer.stop (); }
siehe folgenden Beitrag im Themenbereich Bühnegröße, Event.RESIZE
In As3 gibt es ein Event, welches ausgelöst wird, wenn die Maus die Bühne verlässt. Allerdings gibt es kein Gegenstück, welches ausgelöst wird, wenn die Maus die Bühne betritt. Stattdessen kann man MOUSE_MOVE einsetzen.
import flash.events.MouseEvent; import flash.events.Event; this.stage.addEventListener (MouseEvent.MOUSE_MOVE, playMan); this.stage.addEventListener (Event.MOUSE_LEAVE, stopMan); man.stop (); function playMan (evt:MouseEvent):void { man.play (); } function stopMan (evt:Event):void { man.stop (); }
Gerade im Zusammenhang mit hittest oder überhaupt, wenn man die Mausposition braucht, braucht man oft eine Möglichkeit zu erfahren, ob die Maus die Bühne verlassen hat. Oder anderes ausgedrückt, man will überprüfen, ob die Maus auf der Bühne ist. Dazu gibt es in AS3 einen Event Handler.
this.stage.addEventListener(Event.MOUSE_LEAVE, mouseLeaveListener);
Berühre den folgenden Flashfilm mit der Maus. Sobald über dem rotem Movieclip "mc" ist, bekommt "counter" den Wert "0". Verlasse die Bühne langsam über die obere oder rechte Seite des roten Rechtecks und der Wert 0 bleibt. Ziel ist es jedoch, dass der Wert 0 nur im Falle der Berührung des roten MCs zugewiesen wird.
import flash.events.Event; var curThema= 0; addEventListener(Event.ENTER_FRAME, enterFrameTest); function enterFrameTest (evt:Event):void{ if (mc.hitTestPoint(root.mouseX,root.mouseY,false)) { curThema = 0; }else{ curThema++; } anzeige.text= String(curThema); }
Im folgenden Flashfilm wird abgefragt, ob die Maus die Bühne verlassen hat.
import flash.events.Event; import flash.events.MouseEvent; var curThema:uint = 0; var aktiv:Boolean = true; addEventListener (Event.ENTER_FRAME, counting); this.stage.addEventListener (Event.MOUSE_LEAVE, leaveStage); stage.addEventListener (MouseEvent.MOUSE_MOVE,onMousMove); function counting (evt:Event):void { if (aktiv) { curThema++; } anzeige.text = String(curThema); } function onMousMove (evt:MouseEvent):void { switch (evt.target.name) { case "mc" : aktiv = false; curThema = 0; break; default : aktiv = true; } } function leaveStage (evt:Event):void { trace ("leaving"); aktiv = true; }
Wenn ein Objekt den Keyboard Focus hat wird es das Ziel aller Keyboard-input event dispatches. Das Objekt muss von InteractiveObject erben.
Es kann immer nur ein Objekt zur selben Zeit den keybord Focus haben. Es gibt 3 Möglichkeiten den Focus zu setzen.
Im folgenden Beispiel wird der Focus in ein Textfeld mit Instanznamen myInput per Actionscript gesetzt.
this.stage.focus = myInput;
Oder wenn man ein Textfeld in einem Display Object Container eingefügt hat, kann man auf folgende Weise den focus setzen.
import flash.display.Sprite; import flash.text.TextField; var displCont:Sprite = new Sprite(); var tf:TextField = new TextField(); tf.type = TextFieldType.INPUT; addChild(displCont); displCont.addChild(tf); displCont.stage.focus = tf;
Per Tastatur wird der Focus mit den Tabulator- oder den Pfeiltasten gesetzt. Damit ein Objekt auf diese Weise den Focus erhalten kann, muss es Teil der Flash Tab order sein. Tab order ist eine Liste, die alle Objekte aufführt, welche den Focus erhalten können. Außerdem wird dort die Reihenfolge der Objekte bestimmt, die durch Drücken der Tab Taste nacheinander aufgerufen werden. Es gibt die automatic tab order und die custom tab order. Die automatic tab order ist die Standard tab order, wenn keine custom tab order definiert wurde. Folgende Objekte der Display Liste sind darin enthalten.
Die Reihenfolge wird durch die Position der Objekte bestimmt. Sie geht von links nach rechts und dann von oben nach unten. Die Hierachie der Display Liste spielt hier keine Rolle. Hat ein Objekt den Focus bekommen kann man auch mit den Pfeiltasten die anderen Objekte focussieren.
Die custom tab order wird programmatisch bestimmt, indem man die tabIndex Variable der Objekte auf einen nicht negativen Wert setzt. Die Objekte werden beim Drücken der Tab-Taste vom niedrigsten zum höchsten Wert durchlaufen. Haben 2 Objekte den gleichen tabIndex kommt das Objekt mit der niedrigeren Tiefe depth zuerst.
myObject.tabIndex = 1;
Man schließt ein Objekt aus der tab order aus, indem man die Variable tabEnabled auf false setzt.
myObject.tabEnabled = false;
Außerdem sind alle Objekte deren Variable visible = false ist aus der tab order ausgeschlossen.
Alle Abkömmlinge eines Display Object Container werden aus der tab order ausgeschlossen, indem die Variable tabChildren = false setzt.
myObject.tabChildren = false;
Wenn man mit der Tabulator im folgenden Beispiel die Instanzen der Reihe nach durchläuft, sieht man dass bei dem Kopf der Frau und des Mannes ein animierter Mund erscheint. Der Mund ist ein animierter Button der jeweils innerhalb der beiden Movieclips enthalten ist. Außerdem sieht man die Smileys, die innerhalb des Movieclips Sprechblase enthalten sind. Die Reihenfolge wird also lediglich durch die Position bestimmt, und nicht durch irgendwelche Hierachien innerhalb von Display Listen.
myMovieClip.buttonMode = true;
Standardmäßig erscheint ein gelbes Rechteck, um ein Objekt (Sprite, MovieClip, SimpleButton), welches per keyboard den Focus erhielt. Man kann das gelbe Rechteck für alle Objekte ausschalten, über die stage Variable,
this.stage.stageFocusRect = false;
Man kann das gelbe Rechteck eines einzelnen Objekts über folgende Variable ausschalten. Diese Einstellung übergeht die stageFocusRect Einstellung.
myObject.focusRect = false;
Standarmäßig können nur Textfelder und SimpleButtons den Focus per Maus erhalten. Auch Movieclip und Sprite Instanzen können den Mousefocus bekommen. Dazu ist Folgendes erforderlich:
Um zu Verhindern, dass ein Objekt den MouseFocus bekommt, muss man mouseEnabled auf false setzen
myObj.mouseEnabled = false;
Auf folgende Weise wird verhindert, dass die Abkömmlinge eines Objektes den Mousefocus erhalten:
myObj.mouseChildren = false;
Textfelder erhalten den Mausfocus auch dann, wenn man die tabEnabled Variable der Textfeld Instanz auf false setzt. Das ist ein bug im Flashplayer, der vielleicht irgendwann behoben wird.
Event Type | Target | Standard Verhalten | Datatype | |
---|---|---|---|---|
FocusEvent.FOCUS_IN | Focus wurde erhalten | Das Objekt, welches den Focus erhalten hat. Das Objekt welches den Focus verloren hat wird über relatedObject angesprochen | FocusEvent | |
FocusEvent.FOCUS_OUT | Focus wurde verloren | Das Objekt, welches den Focus verloren hat. Wenn es ein Objekt gibt, welches den focus bekommen hat, kann man es über relatedObject ansprechen. | FocusEvent | |
FocusEvent.FOCUS_KEY_FOCUS_CHANGE | User versucht denFocus mit Keyboard zu ändern | Das Objekt welches den Focus hat. Mit relatedObject wird das Objekt angesteuert, auf den der User den Focus setzen will. | Der Focus wird geändert. Man kann das Verhalten mit preventDefault verhindern. siehe Textbeispiel | FocusEvent |
FocusEvent.FOCUS_MOUSE_FOCUS_CHANGE | User versucht den Focus mit Mouse zu ändern | Das Objekt welches den Focus hat. Mit relatedObject wird das Objekt angesteuert, auf den der User den Focus setzen will. | Der Focus wird geändert. Man kann das Verhalten mit preventDefault verhindern. siehe Textbeispiel | FocusEvent |
Bedenke dass duruch MovieClip(evt.relatedObject) sichergestellt ist, dass es ein MovieClip Objekt ist. Siehe meinen Tipp Typumwandlung
Im folgenden Beispiel bekommt das Input Textfeld, welches den Focus erhält die Hintergrundfarbe beige und welches den Focus verliert die Hintergrundfarbe weiß.
Event Type | Beschreibung | Ziel target | Standard Verhalten | Data Type | Bubbles |
---|---|---|---|---|---|
TextEvent.TEXT_INPUT | User will neuen Text ins Textfeld einfügen | Das Textfeld, in das Text eingefügt werden soll | Text wird ins Textfeld eingefügt. Man kann das Verhalten mit preventDefault verhindern. siehe Textbeispiel | TextEvent | ja |
Event.CHANGE | Neuer Text wurde vom User in ein Input Textfeld eingefügt | Textfeld Object in welches Text eingefügt wurde | Event | ja | |
Event.SCROLL | Textfeld wurde gescrollt, vom User oder programmatisch | Textfeld, das gescrollt wurde | Event | nein | |
TextEvent.LINK | Hypertext Link wurde aktiviert | Textfeld Object, welche Link enthält | TextEvent | ja |
Der Unterschied zwischen TEXT_INPUT und CHANGE ist folgender. TEXT_INPUT bietet die Möglichkeit auf die Bestrebung des Users Text einzugeben zu reagieren und die Aktualisierung zu verhindern oder zuzulassen, während das CHANGE Ereignis auftritt, nachdem der Text im Textfeld aktualisiert wurde.
Siehe Codehinweise
myTextfield.addEventListener (TextEvent.TEXT_INPUT, inputListener); function inputListener (evt:TextEvent):void { trace (evt.text); //Ausgabe der Texteingabe bzw. Zeichens evt.preventDefault (); //verhindert die Aktualisierung des Textes evt.target.text = evt.text; //TextField zeigt nur das letzte eingebene Zeichen an }
Mittelsn preventDefault könnte man den Eingabetext vor der Aktualisierung des Textfeldes formatieren oder anderweitig verändern.
Achtung! Der Scroll Event funktioniert in neueren Browsern nicht mehr.
Das Event.SCROLL Event wird ausgelöst wenn eine der folgenden Variablen ihren Wert ändert: maxscrollH, maxscrollV, scrollH, scrollV
import flash.events.Event; tf.addEventListener(Event.SCROLL, scrollFunktion); function scrollFunktion(evt:Event):void{ trace(evt.target.scrollV); }
Im folgenden Beispiel habe wurde ein Slider progammatisch erstellt. Siehe dazu auch meinenTipp Slider Dort wird die Programmierung des Sliders erklärt.
Wir haben hier 2 Probleme.
import flash.events.Event; import flash.text.TextField; import flash.events.MouseEvent; //Variablen zur Positionierung des Dreiecks var slX:Number = tf.x + tf.width + 10; var slY:Number = tf.y; var slH:Number = tf.height; //--------------------------------------- //Dreieck, Anfasser für Slider wird erzeugt und positioniert var dreieck:Sprite= new Sprite(); this.addChild (dreieck); dreieck.x = slX; dreieck.y = slY; dreieck.graphics.beginFill (0x000000); dreieck.graphics.lineTo (0,0); dreieck.graphics.lineTo (15,-8.75); dreieck.graphics.lineTo (15,8.75); dreieck.graphics.endFill (); // Sensorpunkt Kreis unsichtbar; dreieck.graphics.beginFill (0x000000, 0); dreieck.graphics.drawCircle (9, 0, 16); //drag Slider; var draggin:Boolean = false; //----------------------------------------- tf.addEventListener (Event.SCROLL, onEventScroll); dreieck.addEventListener (MouseEvent.MOUSE_DOWN, onEventMouseDown); stage.addEventListener (MouseEvent.MOUSE_UP, onEventMouseUp); function onEventScroll (evt:Event):void { anzeige.text = "scrollV " + evt.target.scrollV + "\nmaxScrollV " + evt.target.maxScrollV; if (! draggin) { dreieck.y = (tf.height / tf.maxScrollV) * tf.scrollV + slY; } } function onEventMouseDown (evt:MouseEvent):void { draggin = true; var rect:Rectangle = new Rectangle(slX,slY,0,slH); dreieck.startDrag (true, rect); this.addEventListener (Event.ENTER_FRAME, slide); } function slide (evt:Event):void { tf.scrollV = Math.floor((tf.maxScrollV /tf.height) * (dreieck.y-slY)); } function onEventMouseUp (evt:MouseEvent):void { if (draggin) { dreieck.stopDrag (); this.removeEventListener (Event.ENTER_FRAME, slide); draggin = false; } }