2009-10-15 96 views
2

我正在向舞臺添加一些選項卡,並且每個選項卡都會加載它自己的swf文件。我有一個數組跟蹤選項卡,但需要知道每個swf何時加載它屬於哪個選項卡。我不確定最好的辦法。將額外參數傳遞給event.COMPLETE監聽器函數

標籤是由XML控制,因此可以有任意數目的標籤 -

for (var j = 0; j < _xmlTabs.length(); j++) { 
    arrTabs[j] = new Tab(j,_xmlTabs[j].attribute("icon"),_xmlTabs[j]); 
    addChildAt(arrTabs[j],0); 

    mRequest = new URLRequest(_xmlTabs[j].attribute("swf")); 
    mLoader = new Loader(); 
    addChild(mLoader); 
    mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onTabComplete); 
    mLoader.load(mRequest); 
} 

好了,可以說有被加載5個標籤,而且每一個加載自己的SWF和「onTabComplete( )「被炒了5次。即使每個選項卡都按順序創建,但由於swfs的大小不同,因此onTabComplete可能無法順序觸發。那麼如何將每個選項卡與onTabComplete函數關聯?每個實例化的Tab項都有一個可以檢索的「position」屬性。

回答

3

擴展了Loader類的自定義類,加入你想要的新屬性,然後你可以參考它作爲

e.currentTarget.loader.newproperty

在事件處理程序

+0

是否有任何資源顯示如何做到這一點......我熟悉擴展類的概念,但從未做過 – 2009-10-15 16:06:13

+0

它應該在覈心Actionscript文檔中。或者任何AS3書籍的第一或第二章。這是基本的面向對象。 – 2009-10-15 18:13:37

0

我不熟悉Tab類,但Tab是否擴展了DisplayObjectContainer?你也許可以只是:

arrTabs[j].addChild(mLoader); 

,然後在事件處理程序調用:

e.currentTarget.parent.position 

得到處的標籤加載,然後妥善處理或許指標?

+0

什麼是'parent.position'? 'DisplayObjectContainer'沒有這樣的屬性。 – Amarghosh 2009-10-15 15:47:36

+0

謝謝,我試過了,但是它並不能很好地將swf內容添加到選項卡 - 使x和y值混亂。 – 2009-10-15 15:56:36

+0

@JStriedl哎呀。直到現在,我纔看到問題中的「位置」屬性。請對你的答案做一個小小的修改,以便我可以刪除這個投票(它說投票太老了,除非編輯答案,否則不能更改)。 – Amarghosh 2009-10-15 16:19:09

0

爲什麼不用他們各自的URL標識他們?

private function onTabComplete(e:Event):void 
{ 
    var loaderInfo:LoaderInfo = LoaderInfo(e.target); 
    trace(loaderInfo.url); 

    //btw, loaderInfo.content is the tab that you are looking for. 

    var url:String = loaderInfo.url; 
    var tabIndex:Number; 
    for(var j:Number = 0; j < _xmlTabs.length(); j++) 
    { 
    if(url == String(_xmlTabs[j].attribute("swf"))) 
    { 
     tabIndex = j; 
     break; 
    } 
    } 
    //tabIndex now contains the required "j" 
} 

編輯:如果選項卡加載相同的swfs(相同的URL)。

即使這樣做,你應該考慮重新設計。

private function onTabComplete(e:Event):void 
{ 
    int total:Number = _xmlTabs.length(); 
    var loader:Loader = LoaderInfo(e.target).loader; 
    var p:DisplayObjectContainer = loader.parent; 
    if(p.numChildren != total * 2) 
    { 
    trace("other children present : this method won't work"); 
    return; 
    } 

    var ldrIndex:Number = p.getChildIndex(loader); 
    var tabIndex:Number = ldrIndex - total; 
    var matchingTab:Tab = arrTabs[tabIndex]; 
    //enjoy 
} 
+0

更新了代碼 – Amarghosh 2009-10-15 16:06:16

+0

這可以找出加載的swf文件的名稱,這更接近...但是兩個選項卡確實有可能加載相同的swf文件,這可能是個問題 – 2009-10-15 16:08:09

+0

好的,謝謝,請忽略我最後的評論它指的是舊代碼...嘗試這個 – 2009-10-15 16:09:26

0

AS3支持匿名函數一樣,所以你可以做這樣的事情:

addChild(mLoader); 
var handleComplete:Function = function(event:Event):void { 
    onTabComplete(event, j); 
}; 
mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, handleComplete); 
mLoader.load(mRequest); 
+0

假設循環在任何swf加載之前完成(它會),匿名方法內'j'的值總是'_xmlTabs.length()','j'的最終值。自己測試一下 - 這對於你將來避免匿名函數來說是一個足夠好的理由:) – Amarghosh 2009-10-15 15:56:24

+0

Amarghosh是正確的,我實際上已經嘗試過這樣的方法,並且j的值每次都是5。 – 2009-10-15 16:11:40

+0

我相信,如果你在for循環中聲明另一個變量並將其設置爲j並使用它,那麼它將起作用。那樣你每次通過循環引用一個不同的變量,所以每個anon函數引用一個不同的var,而不是所有的引用j本身。 – Herms 2009-10-15 18:07:00

1

修改的thehiatus's answer版本,我認爲應該避開第j值被共享的問題:

function buildHandleComplete(i:int):Function { 
    return function(event:Event):void { 
    onTabComplete(event, i); 
    }; 
} 

for (var j:int = 0; j < _xmlTabs.length(); j++) { 
    arrTabs[j] = new Tab(j,_xmlTabs[j].attribute("icon"),_xmlTabs[j]); 
    addChildAt(arrTabs[j],0); 

    mRequest = new URLRequest(_xmlTabs[j].attribute("swf")); 
    mLoader = new Loader(); 
    addChild(mLoader); 
    var handleComplete:Function = buildHandleComplete(j); 
    mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, handleComplete); 
    mLoader.load(mRequest); 
} 

通過使用一個將索引值作爲參數的函數,並使用該函數構造偵聽器,每個閉包引用一個不同的變量,ins他們中的每一個都引用了j值。

+0

這個技術又被稱爲什麼? – Amarghosh 2009-10-16 05:19:06

+0

功能組成可能嗎?不完全確定。我需要使用任何函數式編程術語已經有一段時間了,我總是混淆這些術語。 – Herms 2009-10-16 15:43:13

+0

或者是咖啡嗎?我完全不記得了。 – Herms 2009-10-16 15:45:14

0

以我的經驗,你會想建立一個加載隊列。加載它們一次一個將防止一些潛在的錯誤

private var j:int = 0; // currentTab number 

private function loadNextTab():void{ 

    arrTabs[j] = new Tab(j,_xmlTabs[j].attribute("icon"),_xmlTabs[j]); 
    addChildAt(arrTabs[j],0); 

    mRequest = new URLRequest(_xmlTabs[j].attribute("swf")); 
    mLoader = new Loader(); 
    addChild(mLoader); 
    mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onTabComplete); 
    mLoader.load(mRequest); 
} 
private function onTabComplete():void{ 
    _xmlTabs[j].attribute("position") 
    //Anything else you want to do to instantiate the object. 

    currentTab++ 
    loadNextTab(); 
} 

不回答你的問題有關傳遞變量,

它不回答我的建議,你的代碼做。

傳遞變量:

一個常用的方法是「自定義事件」

http://flexcomps.wordpress.com/2008/04/29/dispatching-custom-events-in-as3-with-data-or-object/

創建一個擴展事件類,然後一個數據對象添加到事件。您想要包含的任何數據都需要發送到數據對象。

一些其他的方法包括:

匿名函數作爲thehiatus解釋

//errors inside anonymous functions are harder to debug. 

和嵌套函數

private function startLoad():void{ 
    var j:int = 0; 

    //load request calling LoadComplete 

    funciton LoadComplete(e:Event){ 
     //has access to j 
     //errors inside nested functions are harder to debug. 
    } 

}

但這些方法不會有好工作你的fo r循環。你想要訪問的數據可以通過索引訪問,但是你的for循環在任何一個完成加載前都會通過索引。加載隊列是解決當前問題的方法。

祝你好運。

0

這裏是一個快速解決方案! 您可以使用Dictionary對象。

var d:Dictionary=new Dictionary; 
for (var j = 0; j < _xmlTabs.length(); j++) { 
    arrTabs[j] = new Tab(j,_xmlTabs[j].attribute("icon"),_xmlTabs[j]); 
    addChildAt(arrTabs[j],0); 

    mRequest = new URLRequest(_xmlTabs[j].attribute("swf")); 
    mLoader = new Loader(); 
    //associate a tab with his loader... 
    d[mLoader]=arrTabs[j]; 
    // 
    addChild(mLoader); 
    mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onTabComplete); 
    mLoader.load(mRequest); 
} 
// 
function onTabComplete(e:Event):void{ 
    trace("your tab TAB >",d[e.target]); 
} 
0

關聯與標籤中的每個裝載機(標籤有一個鏈接到加載器),然後使用.TARGET成員從事件來獲取完成加載,然後遍歷你的標籤,發現有標籤加載器關聯。

如果你還沒有正確地給它加載引用,你可能需要創建自己的標籤類。

我做了一個類似的例子,加載外部資源並跟蹤他們的進度。