2010-02-15 13 views
1

我有一個關於as3監聽器和一個類的實例的問題。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 

    }  

} 

Button類:

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); 
    } 

} 
} 

回答

1

你的按鈕類可以一個偵聽器添加到舞臺上。如果你的事件發生了泡影,當事件被目標擊中時,它會冒泡到舞臺。按鈕會「聽到」事件並作出迴應。我通常會做你正在做的事情,並將聽衆添加到一個組中。然後,當收到事件時,我循環按鈕,如果event.target與循環中的當前按鈕相同,則將其設置爲「已選中」。

+0

如果我理解正確 - 你說要添加一個監聽器到文檔類 - 但按鈕不會聽到,因爲事件冒泡到頂部,並從來沒有擊中其他實例 - 除非我錯了。 我遇到了這個問題:它迫使我跟蹤所有創建的按鈕(一個數組,通過調度調用方法調用實例來循環),並失去了我正在尋找的自我感知方法。這種方式基本上與組相同。 我喜歡保持所有的按鈕管理遠離文檔類... 如果我誤解了,你會介意詳細說明嗎? – Beans 2010-02-15 16:12:45

+0

不是文檔類,而是舞臺。 stage.addEventListener();會在你的按鈕類中。 – typeoneerror 2010-02-15 16:50:41

+0

福里斯特樹爲什麼?謝謝。我覺得那個失去了眼鏡的人只能在頭頂上找到他們。 作爲腳註 - 以這種方式添加舞臺監聽器,與組和管理器方法相比,它被認爲是不好的形式嗎? – Beans 2010-02-15 17:31:29

0

對於AS3來說也是比較新的,但是我最近在事件監聽器方面做了很多工作。向舞臺添加事件監聽器的問題在於,只要該事件觸發舞臺,就會觸發。此外,如果事件偵聽器是類的一部分,並且您添加了該類的10個實例,則該階段現在將有10個事件偵聽器執行相同的操作,並且它們都將觸發。如果你想要區分(每個按鈕都有不同的做法),那麼你就必須循環它們,這樣就失去了試圖將它加入舞臺的全部目的。

我一直在做的是不使用事件監聽器來處理任何事情,而是使用低級對象中的自定義事件。假設我有三個按鈕,當他們(並且只有他們)被點擊時,我想要做不同的事情。那麼,爲了顯示他們將不得不被添加爲什麼東西的孩子,對吧?我將一個事件監聽器添加到他們的父代,然後調用我想從父代發生的函數。像這樣:

(注:這是不是實際的代碼更僞代碼)

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來查找對象。你也可以防止所有的按鈕立即開火,當然他們可以做不同的事情。

相關問題