Actionscript3.0 里的用户事件流,以及如何利用

来源:互联网 发布:matlab数据预测实例 编辑:程序博客网 时间:2024/06/08 03:30

I am talking about this topic, because I encounter a problem with event flow design when working on my new project - which we call it iKeleido.


This involves the event framework in Actionscript3.0, and the details can be found in any book, such as [Actionscript3 Bible]; within it the author drew a picture to illustrate how does events flow within a Flash run-time environment(please note that the event here should not be regarded as all events, it just means the user interaction event, normally mouse event):

event-framework


I will not go through with this book, instead, let's focus on my topic, and now create a program. Create four MovieClips into the library, with attached empty ActionScript classes:

mcs


And now create a container class, which will hold all of them:

package  {import flash.display.Sprite;import flash.events.MouseEvent;public class TableCloth extends Sprite{private var _skirt:Sprite;private var _coffeeGrinder:Sprite;private var _car:Sprite;private var _cup:Sprite;public function TableCloth() {this.graphics.beginFill(0xF7DFAF);this.graphics.drawRect(0,0,600,400);this.graphics.endFill();}public function build():void{this._skirt = new Skirt();this._skirt.name = "SKIRT";this._skirt.x = 500;this._skirt.y = 100;this.addChild(this._skirt);this._skirt.addEventListener(MouseEvent.CLICK, this.objectClickedHandler);this._coffeeGrinder = new CoffeeGrinder();this._coffeeGrinder.name = "COFFEEGRINDER";this._coffeeGrinder.x = 400;this._coffeeGrinder.y = 100;this.addChild(this._coffeeGrinder);this._coffeeGrinder.addEventListener(MouseEvent.CLICK, this.objectClickedHandler);this._car = new Car();this._car.name = "CAR";this._car.x = 200;this._car.y = 100;this.addChild(this._car);this._car.addEventListener(MouseEvent.CLICK, this.objectClickedHandler);this._cup = new Cup();this._cup.name = "CUP";this._cup.x = 60;this._cup.y = 100;this.addChild(this._cup);this._cup.addEventListener(MouseEvent.CLICK, this.objectClickedHandler);}private function objectClickedHandler($e:MouseEvent):void{trace($e.target.name + " get clicked.");}}}


And now is the document class definition:

package  {import flash.display.MovieClip;import flash.events.Event;import flash.events.MouseEvent;public class main extends MovieClip{private var _tableCloth:TableCloth;public function main() {this.addEventListener(Event.ADDED_TO_STAGE, this.addedToStageHandler);}private function addedToStageHandler($e:Event):void{this._tableCloth = new TableCloth();this._tableCloth.x = 100;this._tableCloth.y = 50;this._tableCloth.build();this.addChild(this._tableCloth);this._tableCloth.addEventListener(MouseEvent.CLICK, this.clickedHandler);}private function clickedHandler($e:MouseEvent):void{trace("TABLE CLOTH get clicked!!");}}}



Let's try it.

program-interface


Clicking on the graphics will get output like:

CAR get clicked.TABLE CLOTH get clicked!!

Clicking only within the yellow area and outside the graphics, will get:

TABLE CLOTH get clicked!!


So far, this program only demostrates the idea of event propagation in Actionscript3. Now let's add something.


Within all the handling methods, add extra lines:

trace($e.eventPhase);


Clicking on one graphic will get:

COFFEEGRINDER get clicked.2TABLE CLOTH get clicked!!3

And clicking on table will get:

TABLE CLOTH get clicked!!2


Number 2 indicates that the event is at TARGET PHASE(EventPhase.AT_TARGET), whereas 3 indicates BUBBLING PHASE(EventPhase.BUBBLING_PHASE). So, this results tells that, thecapturing process doesn't happen by default; only bubbling process occurs, so the handlers more close to the target will get triggered earlier.


And, now, remove those lines, and:


Open file TableCloth.as, within the body of method objectClickedHandler(), add lines:

if("CAR" == $e.target.name){$e.stopPropagation();}


In effect, we will find that, clicking on the car will get tht output:

CAR get clicked.


And nothing eles, which means the event doesn't trigger the event handler attached to_tableCloth within main class,here is online doc about stopPropagation() & stopImmediatePropagation().


mouseEnabled & mouseChildren


Now we will explore the approaches to stop the mouse events getting dispatched from a specific display object, add two buttons and some text fields to the stage, and change themain.as to:

package  {import flash.display.MovieClip;import flash.events.Event;import flash.events.MouseEvent;public class main extends MovieClip{private var _tableCloth:TableCloth;public function main() {this.addEventListener(Event.ADDED_TO_STAGE, this.addedToStageHandler);}private function addedToStageHandler($e:Event):void{this._tableCloth = new TableCloth();this._tableCloth.x = 100;this._tableCloth.y = 50;this._tableCloth.build();this.addChild(this._tableCloth);this._tableCloth.addEventListener(MouseEvent.CLICK, this.clickedHandler);mEblTxt.text = this._tableCloth.mouseEnabled ? "mouse enabled" : "mouse disabled";mChlTxt.text = this._tableCloth.mouseChildren ? "yes" : "no";mouseEblBtn.addEventListener(MouseEvent.CLICK, this.togMousEblBtnPressedHandler);mouseCdlBtn.addEventListener(MouseEvent.CLICK, this.togMousCdlBtnPressedHandler);}private function clickedHandler($e:MouseEvent):void{trace("TABLE CLOTH get clicked!!");//trace($e.eventPhase);}private function togMousEblBtnPressedHandler($e:MouseEvent):void{this._tableCloth.mouseEnabled = ! this._tableCloth.mouseEnabled;mEblTxt.text = this._tableCloth.mouseEnabled ? "mouse enabled" : "mouse disabled";}private function togMousCdlBtnPressedHandler($e:MouseEvent):void{this._tableCloth.mouseChildren = ! this._tableCloth.mouseChildren;mChlTxt.text = this._tableCloth.mouseChildren ? "yes" : "no";}}}


We now have a program like:

program-with-buttons


Let's play with it, firstly, press button 'toggle mouseEnabled', to set it to false. Then clicking on the yellow area(outside any graphic of course) will get nothing output, but clicking on cup will get output:

CUP get clicked.TABLE CLOTH get clicked!!


Well, it may seem weird, since the TableCloth instance has mouseEnabled set to false, why we get mouse event on it? Actually, it is because mouseEnabled property will not confine the child elements, it only affects its self. And it can still receive its children's event during bubbling process.


This moment, clicking on car graphic will still get:

CAR get clicked.


Now, press button 'toggle mouseChildren'. Now we disable both the TableCloth instance and its children. Clicking on any thing will output nothing.

Then press button 'toggle mouseEnabled', to set it back to true. Then clicking on the yellow area(outside any graphic of course) will get:

TABLE CLOTH get clicked!!

There is nothing to explain.

Then click on any graphic, you will see:

TABLE CLOTH get clicked!!

Because the children are forbidden to dispatch mouse event, so the target is replaced with TableCloth instance itself.


So far, the hierarchy of the DisplayObjects is only two-depth, I should add one more to demonstrate some other language features, however, my penitence has run off. I am so eager to start my problem.


Here is iKeleido's interface:

ikeleido


And let's abstract the situation this program reflects:


First of all, we have a display container, say, ConA, and it is top level container of all this visual elements, visually, you can regard it as the collection of the visual elements except: the wooden background, the potted flower, the notebook;

Secondly, we have one very complex SpriteX(like the PavoMenu in my example), and SpriteY(like the main content), SpriteX also has many children display objects, and pretty complex animation, so is the main content; 

Then, ConA need to keep track of the states of SpriteX and SpriteY, it will mainly be responsible for control the logic of main content's animation, since SpriteX is very self-managed.



原创粉丝点击