跨对象实例的AS3侦听器 - 可能/好或坏的做法?

时间:2010-02-15 16:01:20

标签: flash actionscript-3 oop event-handling

我有关于as3侦听器和类实例的问题。

主要问题:有没有办法从按钮实例调度事件,以便其他按钮实例可以监听(不需要文档类中的监听器)

假设我有一个文档类和一个按钮类。该文档将有几个按钮类的实例添加到显示列表中。选择按钮时,将调用set方法将所选的包变量设置为该实例。从这里开始我想发送一个事件来通知所有其他实例。

|document
|-button instance 1
|-button instance 2
|-button instance 3 (i want to send an event directly to instance 1 and 2...)

我目前的解决方案是创建一个buttonGroup类,实例化按钮,按钮会向组父级发送事件调用。

|document
|-button group (catch the event and send an event to all instances within the group)
|---button instance 1
|---button instance 2
|---button instance 3 (dispatch  the event)

但我的问题仍然存在 - 如果我有多个组并且我想向所有组实例发送一个事件..那么我需要一个buttonManager类来跟踪组(或者至少,这就是我的方式)明白了吗?)

|document
|-button manager (catch the event and send an event to all group instances)
|
|---button group 1
|-----button instance 1
|-----button instance 2
|-----button instance 3 (dispatch  the event)
|
|---button group 2
|-----button instance 1
|-----button instance 2
|-----button instance 3 (dispatch  the event)

我并不反对这些“解决方案”,我只是好奇是否有另一种方式,或者实际上我的解决方案是一个好的做法。我的代码的基础位于下面(减去按钮管理器和组类)

我希望这个描述性足够,温柔,我是OOP的新手...... 提前谢谢。

document.as

import flash.display.*;
import flash.events.*;
import myClasses.events.ButtonEvent;

public class Document extends MovieClip {       

    public function Document(){
        trace("initialising Document...");
        addEventListener(Event.ADDED_TO_STAGE, popStageVars);           
    }   


    private function popStageVars(e:Event){
        trace("popping stage vars...")

        var ob1:AbstractOBJ = new AbstractOBJ           
        var ob2:AbstractOBJ = new AbstractOBJ           
        var ob3:AbstractOBJ = new AbstractOBJ

        addChild(ob1)
        addChild(ob2)
        addChild(ob3)


        ob1.selected = ob1
        ob2.selected = ob2
        ob3.selected = ob3

    }       

}

按钮类:

import flash.display.*; 
import flash.events.*;
import myClasses.events.ButtonEvent;

public class ButtonOBJ extends MovieClip  implements IEventDispatcher {

    internal static var _selected:Object = null

    public function ButtonOBJ(){
        trace("initialising ButtonOBJ...");         
        addEventListener(Event.ADDED_TO_STAGE, popStageVars);
        addEventListener(AbstractEvent.SET_CUR, checkClip);
    }


    private function popStageVars(e:Event){
        trace("popping stage vars..." + this.name)
    }       

    private function checkClip(e:AbstractEvent){
        trace("checking button registered... " + this.name)
    }

    public function get selected():Object{
        return _selected                        
    }

    public function set selected(s:Object):void{
        var sName:String 

        if(selected != null){
            sName = selected.name
        }else{
            sName = null
        }

        trace(this.name + " is changing the current selected from: " + sName + " - to: " + s.name)          

        _selected = s
        dispatchEvent(new AbstractEvent(AbstractEvent.SET_CUR, true));  
    }       

}

以及buttonEvent:

package myClasses.events{       

import flash.events.Event;

public class ButtonEvent extends Event {

    public static const SET_CUR:String = "setSelected";
    public static const VERSION:Number = 1.0;

    public function ButtonEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) {         
        super(type, bubbles, cancelable);
    }

    public override function clone():Event {
        return new ButtonEvent(this.type, this.bubbles, this.cancelable);
    }   

}
}

2 个答案:

答案 0 :(得分:1)

您的按钮类可以向舞台添加一个侦听器。如果你的事件冒泡,当目标触发事件时,它会冒泡到舞台上。该按钮将“听到”该事件并作出响应。我通常会做你正在做的事情并将听众添加到一个组中。然后我在收到事件时循环浏览按钮,如果event.target与循环中的当前按钮相同,则设置为“选中”。

答案 1 :(得分:0)

AS3也相对较新,但我最近在事件听众方面做了很多。向舞台添加事件侦听器的问题是,只要该事件发生在舞台上,它就会触发。此外,如果事件监听器是一个类的一部分,并且您添加了该类的10个实例,那么该阶段现在将有10个事件监听器都执行相同的操作,并且它们都将触发。如果你想要区分(AKA每个按钮做一些不同的事情),你无论如何都必须循环它们,这就是试图将它添加到舞台上的全部目的。

我一直在做的事情是除了我的低级对象中的自定义事件之外没有使用事件侦听器。让我们说我有三个按钮,当他们(并且只有他们)被点击时,我想做不同的事情。好吧,为了表现出来,他们将不得不作为孩子的东西加入,对吗?我将一个事件监听器添加到它们的父级,然后从父级调用我想要发生的函数。像这样:

(注意:这比实际代码更伪代码)

public class ParentObject extends Sprite{
    public ParentObject(){
        addchild(new ButtonObject1());
        addchild(new ButtonObject2());
        addchild(new ButtonObject3());
        addEventListener(MouseEvent.CLICK, doButtonThing);
    }

    private doButtonThing(e:MouseEvent):void{
        if(e.target is ButtonObject){
            e.target.doStuff();
        }
    }
}

public ButtonObject1 extends ButtonObject{ //This works for 2 and 3. Also note that all three objects extend a parent class called ButtonObject. This is useful in checking the event target.
    public ButtonObject1(){
        //Create the Object here.
    }

    public doStuff():void{
         //Whatever you want the button to do
    }

}

单击某些内容时,父对象将捕获该事件。然后它将检查点击的对象是否是ButtonObject(1,2或3;如果它不是按钮,我们不想要触发某些东西)。如果是,则调用单击的doStuff函数而不是其他函数。您不必显式跟踪它们,因为它使用event.target来查找对象。你也可以防止所有按钮一下子触发,当然他们都可以做不同的事情。