我有一个加载其他几个 swf 的主要“父” swf。如果主 swf 发生了什么事,我需要告诉其中一个子 swf。
反过来,这似乎也很有效。任何孩子都可以简单地 dispatchEvent(),我可以设置主 swf 来监听事件。但是,我无法让子 swf 捕获父发送的任何事件。它是如何完成的?
我有一个加载其他几个 swf 的主要“父” swf。如果主 swf 发生了什么事,我需要告诉其中一个子 swf。
反过来,这似乎也很有效。任何孩子都可以简单地 dispatchEvent(),我可以设置主 swf 来监听事件。但是,我无法让子 swf 捕获父发送的任何事件。它是如何完成的?
好的,所以如果您已经知道其中的大部分内容,我很抱歉……但这似乎是一个很常见的问题,并且不是很明显。
在 AS3 中,由显示列表上的对象调度的事件可以在它们在显示列表层次结构中冒泡时被侦听,而无需指定原始对象。(当然假设事件的冒泡属性设置为 true)。因此文档类(_root 的旧概念)可以响应来自任何显示对象的鼠标点击,无论嵌套多深,
addEventListener(MouseEvent.CLICK, _onMouseClick)
在任何其他情况下-例如冒泡设置为false,广播者不是显示列表上的InteractiveObject,或者(如您的情况)侦听器低于显示列表层次结构中的广播者-广播事件的对象必须是具体听过:
fooInstance.addEventListener(Event.BAR, _bazFunc)而不仅仅是
addEventListener(Event.BAR, _bazFunc)
基本上,您需要将对父对象的引用传递给您的子 swf,以便它可以将事件处理程序附加到它。
一种方法是通过显示列表将子类的事件分派给父类(一旦子类加载并完全初始化)。父级使用此事件的 event.target 属性来引用子级并在其上设置 parentClass 变量。然后可以使用它来附加侦听器:
package {
class ChildClass
{
private var __parentClass:ParentClass;
// EventID to listen for in ParentClass
public static const INITIALISED:String = "childInitialised";
// Constructor
function ChildClass()
{
// Do initialising stuff, then call:
_onInitialised();
}
private function _onInitialised():void
{
// Dispatch event via display hierarchy
// ParentClass instance listens for generic events of this type
// e.g. in ParentClass:
// addEventListener(ChildClass.INITIALISED, _onChildInitialised);
// function _onChildInitialised(event:Event):void {
// event.target.parentClass = this;
// }
// @see mutator method "set parentClass" below
dispatchEvent(new Event(ChildClass.INITIALISED, true);
}
public function set parentClass(value:ParentClass):void
{
__parentClass = value;
// Listen for the events you need to respond to
__parentClass.addEventListener(ParentClass.FOO, _onParentFoo, false, 0, true);
__parentClass.addEventListener(ParentClass.BAR, _onParentBar, false, 0, true);
}
private function _onParentFoo(event:Event):void
{
...
}
}
}
调度自定义 ChildSWFEvent - 即,而不是使用上面的类定义常量 - 将使这成为一个更灵活的解决方案,因为 ParentClass 实例可以侦听由任何子 swf 广播的公共 ChildSWFEvent.INITIALISED 事件,其中包含作为附加传递的上下文有用信息范围。
在父 swf (Index.swf) 中加载子 swf (Main.swf) 时,请在字段变量或类变量中保留引用
fldMain = BulkLoader.getLoader("Index").getContent("Main.swf") as DisplayObject;
this.addChild(fldMain);
(我正在使用BulkLoader加载任何内容)
等待调度事件直到添加孩子(ADDED_TO_STAGE
事件)是一个很好的做法
当我想向我的孩子发送一个事件时,我只是说:
fldMain.dispatchEvent(new CustomEvent(CustomEvent.INIT_CHILD,data));
我会倾听每个孩子
Event.ADDED_TO_STAGE
一旦它被添加到舞台上,您就可以参考/收听舞台上的事件。
例子
//Child
if(stage) _init(); //Already added
else addEventListener(Event.ADDED_TO_STAGE, _init); //waiting to be added
private function _init(e:Event = null):void
{
stage.addEventListener(CustomEvent.CHANGED, _onStageChanged);
{
我没有对此进行测试,但只要您从舞台分派事件,它就可以工作。
//stage
dispatchEvent(new CustomEvent(CustomEvent.CHANGED));
如果您正确设置自定义事件类,您还可以传递信息。
我所做的是在将孩子添加到舞台后在父母身上添加一个监听器以进行更改。现在,只要您想让孩子处理自己的更新,只需Event.CHANGE
从父母那里分派。冒泡可以是真的也可以是假的。
我认为,如果您将孩子的侦听器附加到舞台(stage.addEventListener...
),任何抛出 a 的对象Event.CHANGE
都可能触发孩子处理事件。
package
{
import flash.display.*
import flash.events.*
public class Child extends Sprite
{
public function Child():void
{
this.addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler, false, 0, true);
}
private function addedToStageHandler(pEvent:Event):void
{
trace("CHILDADDED");
this.removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
this.parent.addEventListener(Event.CHANGE, parent_changeEventHandler, false, 0, true);
}
private function parent_changeEventHandler(pEvent:Event):void
{
trace("PARENT_CHANGED");
}
}
}
IMO,孩子了解或关心父母几乎是不合适的。另一方面,父母几乎总是知道他们孩子的一切(因为他们直接提到了他们)。因此,在这种情况下,我只需在子类上创建一个属性或方法,可以在需要时由父类设置/调用。
这具有更好的性能优势,因为创建和处理事件比简单地调用方法或设置值更昂贵。
HTH;
艾米