将额外参数传递给event.COMPLETE侦听器函数

时间:2009-10-15 15:18:10

标签: flash actionscript-3

我在舞台上添加了一些标签,每个标签都会加载自己的swf文件。我有一个数组跟踪选项卡,但需要知道每个swf何时加载它所属的选项卡。我不确定最好的方法。

标签由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次。即使按顺序创建每个选项卡,onTabComplete也可能无法按顺序触发,因为swfs的大小不同。那么如何将每个选项卡与onTabComplete函数相关联?每个实例化的Tab项都有一个可以检索的“position”属性。

8 个答案:

答案 0 :(得分:3)

使用自定义类扩展Loader类,添加所需的新属性,然后可以将其引用为

e.currentTarget.loader.newproperty

在事件处理程序

答案 1 :(得分: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);
}

通过使用一个函数,该函数将索引值作为参数并使用它构建监听器,最后每个闭包引用一个不同的变量,而不是它们都引用j值。

答案 2 :(得分:0)

我不熟悉Tab类,但Tab是否扩展了DisplayObjectContainer?你可以做到:

arrTabs[j].addChild(mLoader);  

然后在事件处理程序调用中:

e.currentTarget.parent.position

获取加载了哪个标签的指标,然后可能正确处理?

答案 3 :(得分:0)

为什么不用各自的网址识别它们?

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(相同的网址)。

即使这样做,你也应该考虑重新设计。

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
}

答案 4 :(得分:0)

AS3也支持匿名函数,所以你可以这样做:

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

答案 5 :(得分: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/

创建一个扩展Event的类,然后将一个数据对象添加到Event中。然后,您需要包含的任何数据都需要发送到数据对象。

其他一些方法包括:

匿名函数如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.
   }

}

但这些方法也不适用于你的for循环。您要访问的数据可通过索引访问,但您的for循环在任何完成加载之前都会通过索引。加载队列是解决当前问题的方法。

祝你好运。

答案 6 :(得分: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]);
}

答案 7 :(得分:0)

将每个加载器与选项卡相关联(选项卡具有指向加载程序的链接),然后使用事件中的.target成员获取已完成的加载程序,然后遍历选项卡以查找具有该加载程序关联的选项卡。

如果您还没有正确地提供它来保存对加载器的引用,您可能必须创建自己的选项卡类。

我做了一个类似的例子来加载外部资源并跟踪他们的进度。