Странное поведение переменной AS3 - PullRequest
0 голосов
/ 30 сентября 2010

ОК, вот что я пытаюсь сделать:

У меня есть целевая страница с 3 кнопками, и у меня есть 3 соответствующих внешних SWF-файла, по одному для каждой кнопки ... так чтопользователь нажимает кнопку, и соответствующий файл SWF загружается в пустой MC на сцене.Теперь каждый из этих внешних SWF-файлов также содержит несколько кнопок, и каждая из этих кнопок при нажатии запускает событие click, каждое событие кнопок в каждом SWF-файле имеет уникальное имя в зависимости от имени кнопки и имени SWF-файла (например, swf1_button1_click).в основном SWF-файле после нажатия кнопки я перебираю 3 основные кнопки и добавляю прослушиватели к содержимому клипа пустого держателя для каждой из кнопок, чтобы он прослушивал «swf1_button1_click», «swf1_button2_click», «swf2_button1_click» ... так далее и так далее.

Теперь все это работает, клипы загружаются правильно, события запускаются и слышатся соответствующим образом, что означает, что пустой клип действительно получает событие "swf1_btn1_click" и корректно запускает код, связанный с этим событием, но проблема заключается ввызываемая функция Вот код, о котором идет речь ...

Функция загрузки внешних SWF-файлов:

function loadCommunity(e:MouseEvent) {
 var mLoader:Loader = new Loader();
 var community:String = MovieClip(e.currentTarget).name;
 trace("Loading " + community);
 var mRequest:URLRequest = new URLRequest(DevSite+"/flash/" + community + ".swf?community=" + community);
 mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, displayCommunity);
 mLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, function(e:ProgressEvent) {
  var percent:Number = e.bytesLoaded / e.bytesTotal;
  percent = Math.round(percent * 100);
  trace(percent + "% loaded");
 });
 mLoader.load(mRequest);
}

Код для назначения прослушивателей событий:

function displayCommunity(e:Event) {
 for (var i = 0; i < mcCommunityHolder.numChildren; i++) {
  mcCommunityHolder.removeChild(mcCommunityHolder.getChildAt(i));
 }
 mcCommunityHolder.alpha = 0;
 mcCommunityHolder.visible = true;
 mcCommunityHolder.addChild(e.currentTarget.content);
 TweenLite.to(mcCommunityHolder, 1, {alpha:1, easing:Elastic.easeOut});
 var newClip:MovieClip = MovieClip(mcCommunityHolder.getChildAt(mcCommunityHolder.numChildren - 1));

 for each (var mc:MovieClip in mcCommunities) {
  var commName:String = mc.name.toLowerCase();
  trace(" ... " + commName + " ... ");
  newClip.addEventListener(commName + "_btnMap", function(e:Event) { trace("clicked: " + commName); viewLotmap(commName); });
  newClip.addEventListener(commName + "_btnLocation", function(e:Event) { trace("clicked: " + commName); viewLocationmap(commName); });
  newClip.addEventListener(commName + "_btnAriel", function(e:Event) { trace("clicked: " + commName); arielPhotos(commName); });
  newClip.addEventListener(commName + "_btnRegister", function(e:Event) { trace("clicked: " + commName); communityRegister(commName); });
 }
}

Итак, что я получаю: независимо от того, какую кнопку внешнего SWF я нажал, события кнопок внутри нее действуют так, как если бы я нажимал кнопку из внешнего SWF 3 ... имеет смысл?

вот пример: я нажимаю кнопку 1, внешний SWF 1 загружается и отображается, внутри внешнего SWF 1 я нажимаю кнопку 1, которая запускает свое событие "swf1_btn1_click", и основной SWF видит его как таковой, но когда эта функция ("communityRegister(commName); ") вызывается в событии слушателя," commName "всегда одно и то же значение (значение, которое btn3 от maiN SWF должен иметь).

Таким образом, моя основная часть флеш-памяти обрабатывает все внешние события SWFS, как если бы они происходили от внешнего SWF-файла 3. Лучший способ объяснить это так: он обрабатывает «commName: String», как если бы он был ссылочной переменной.и когда я оставляю его на каждой итерации цикла, предыдущие его использования также меняются на новое значение, поэтому каждый раз, когда я его использую, всегда устанавливается значение последнего раза, когда он был назначен ...

Гаххххххххххххххххх ...Мне всегда удавалось перерабатывать код, пока он не исправился, но я устал от этого и хочу знать, почему это происходит.Меня не интересуют другие способы кодирования того, что я хочу делать, мне нужно знать, что вызывает такое поведение, так что не стесняйтесь получить техническую информацию;)

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 01 октября 2010

Edit: Doh, ха-ха, я только что перечитал комментарий выше, и этот метод на самом деле является вторым предложением, которое он сделал, я немного хотел попробовать его первые предложения и потерпел неудачу ... о, хорошо, яЯ оставлю этот оригинальный комментарий здесь, потому что он объясняет, почему первое предложение не будет работать, а второе работает ...

Хорошо, поэтому ваше объяснение обоснованно, но ваше решение не работаетработа ... Вот почему:

вы сказали добавить свойство в мувиклип, которое содержит значение «commName», чтобы устранить проблему со ссылочной переменной, что и нужно (хотя «commName» только что назначензначение "mc.name", чтобы вы могли просто использовать вместо него "mc.name"), но проблема со ссылками все еще существует, потому что мы находимся в цикле for ...

for each (var mc:MovieClip in mcCommunities)...

Так что "mc"все еще рассматривается как ссылочная переменная, и мы все еще получаем те же самые нежелательные результаты (каждое событие объекта действует так, как если бы оно было нажатием последнего объекта в строке ...)

Так как же это исправить ...Ну что яв конечном итоге я сделал замену «для каждого» на «для» (var i: int ...) и захват «mc» с помощью метода «getObjectAt (i)», который сначала я думал, что будет работать, но оказалось, что мы все ещеесть переменная, которая действует как ссылка, и на этот раз она была «i: int» в итерации ... так что это:

for (var i:int = 0;  i < mcCommunities.numChildren; i++) {
MovieClip(mcCommunities.getChildAt(i)).name);   ...

, где mcCommunities.numChildren равен 3 (0,1,2), вызваноi равняется 3 (недопустимый индекс), когда цикл завершается, и везде я установил «MovieClip (mcCommunities.getChildAt (i)). name);», прежде чем теперь рука имела 3 в качестве значения для i ... фрустрация

Итак, окончательное рабочее решение было следующим:

function displayCommunity(e:Event) {
    for (var i = 0; i < mcCommunityHolder.numChildren; i++) {
        mcCommunityHolder.removeChild(mcCommunityHolder.getChildAt(i));
    }
    mcCommunityHolder.alpha = 0;
    mcCommunityHolder.visible = true;
    mcCommunityHolder.addChild(e.currentTarget.content);
    TweenLite.to(mcCommunityHolder, 1, {alpha:1, easing:Elastic.easeOut});

    for (var j:int = 0;  j < mcCommunities.numChildren; j++) {
        assignListeners(MovieClip(mcCommunityHolder.getChildAt(mcCommunityHolder.numChildren - 1)), MovieClip(mcCommunities.getChildAt(j)).name);
    }
}

function assignListeners(newClip:MovieClip, commName:String) {
    newClip.addEventListener(commName + "_btnMap", function(e:Event) { trace("clicked: " + commName); viewLotmap(commName); });
    newClip.addEventListener(commName + "_btnLocation", function(e:Event) { trace("clicked: " + commName); viewLocationmap(commName); });
    newClip.addEventListener(commName + "_btnAriel", function(e:Event) { trace("clicked: " + commName); arielPhotos(commName); });
    newClip.addEventListener(commName + "_btnRegister", function(e:Event) { trace("clicked: " + commName); communityRegister(commName); });
}

Что я сделал, так это вынул назначение eventListeners и поместил его в функцию, так что теперь везде, гдевызывал ссылочную переменную, прежде чем теперь назначался через параметры функции, которые находятся только в области действия самой функции, поэтому каждый раз, когда вы вызываете ее, вы можете быть уверены, что значения будут теми, что вы отправили;) удовлетворение

ЛюбойКак, спасибо, что указали мне в правильном направлении, я теперь обернул голову вокруг этого, и я могу найти другую, кажущуюся нелогичной проблему, чтобы вырвать мои волосы:)

Peace

0 голосов
/ 01 октября 2010

Я думаю, вы уже обнаружили проблему.Все слушатели событий заканчивают ссылкой на commName, созданный на последней итерации вашего цикла.

Есть несколько способов обойти это.Вверху головы:

  for each (var mc:MovieClip in mcCommunities) {
  var commName:String = mc.name.toLowerCase();
  trace(" ... " + commName + " ... ");
  newClip.commName = commName;
  newClip.addEventListener(commName + "_btnMap", function(e:Event) { trace("clicked: " + e.target.commName); viewLotmap(e.target.commName); });
  newClip.addEventListener(commName + "_btnLocation", function(e:Event) { trace("clicked: " + commName); viewLocationmap(e.target.commName); });
  newClip.addEventListener(commName + "_btnAriel", function(e:Event) { trace("clicked: " + e.target.commName); arielPhotos(e.target.commName); });
  newClip.addEventListener(commName + "_btnRegister", function(e:Event) { trace("clicked: " + e.target.commName); communityRegister(e.target.commName); });
 }

Здесь идея в том, что, поскольку MovieClip является динамическим, вы можете добавить commName в качестве свойства.Затем в обработчике событий вы получаете доступ к этому значению из экземпляра mc.

Другой вариант может быть следующим:

 for each (var mc:MovieClip in mcCommunities) {
  var commName:String = mc.name.toLowerCase();
  trace(" ... " + commName + " ... ");
  setEvents(newClip,commName);
 }

 function setEvents(mc:MovieClip,commName:String):void {
  mc.addEventListener(commName + "_btnMap", function(e:Event) { trace("clicked: " + commName); viewLotmap(commName); });
  mc.addEventListener(commName + "_btnLocation", function(e:Event) { trace("clicked: " + commName); viewLocationmap(commName); });
  mc.addEventListener(commName + "_btnAriel", function(e:Event) { trace("clicked: " + commName); arielPhotos(commName); });
  mc.addEventListener(commName + "_btnRegister", function(e:Event) { trace("clicked: " + commName); communityRegister(commName); }); 
 }

Передача commName в качестве аргумента должна предотвратить то, что mcs имеет одинаковое значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...