Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   for не выполняет всех интераций!!! О_О (http://www.flasher.ru/forum/showthread.php?t=165913)

CrazyPHP 28.08.2011 05:04

for не выполняет всех интераций!!! О_О
 
Имеется следующий кусок кода:
Код AS3:

//очистим карту
trace(map_layer.numChildren);
for(var i=0; i<map_layer.numChildren; i++){
    trace(i);
    //удалим
    map_layer.removeChildAt(i);
    //
}
//

вывод trace вот такой:
Код AS3:

7
0
1
2
3

т.е. детей он насчитал 7, а интераций выполнил 4. Как это возможно? Бред какойто!

Добавлено через 10 минут
Сделал вот так заработало, кто бы мог подумать, индексы в массиве детей изменяются динамически... хмм..
Код AS3:

//очистим карту
                        trace(map_layer.numChildren);
                        var child_count = map_layer.numChildren-1;
                        for(var i=child_count; i>=0; i--){
trace(i);
                                //удалим сам объект
                                map_layer.removeChildAt(i);
                                //
                        }
                        //


saikspaik 28.08.2011 05:15

Ну так ты с помощью removeChildAt(i), уменьшаешь количество детей, поэтому все выполняется как положено.
Запиши в переменную количество детей, а потом используй его в цикле.

Добавлено через 14 минут
Цитата:

кто бы мог подумать, индексы в массиве детей изменяются динамически... хмм..
Хм, как бы им еще изменяться?

ProxyGreen 28.08.2011 09:14

Код AS3:

while (map_layer.numChildren > 0) {
                          map_layer.removeChildAt(0);
                  }


vorodis2 28.08.2011 12:10

Если те всех нужно прибить я делаю
Код AS3:

for(i=0; i>2; i++){
  if(map_layer.numChildren > 0) {map_layer.removeChildAt(0); i=0; }
}


СлаваRa 28.08.2011 12:40

вот еще вариант

Код AS3:

while (контейнер.numChildren) 
    if (удаляемый_клип.parent)
        контейнер.removeChild(удаляемый_клип)


kackbip 28.08.2011 12:44

Цитата:

2ProxyGreen, если не проверять наличие родителя, могут возникать ошибки
В примере, который привел 2ProxyGreen, нет смысла проверять наличие parent.

i.o. 28.08.2011 12:52

Цитата:

Сообщение от vorodis2 (Сообщение 1026165)
Если те всех нужно прибить я делаю
Код AS3:

for(i=0; i>2; i++){
  if(map_layer.numChildren > 0) {map_layer.removeChildAt(0); i=0; }
}


Тяжелое прошлое в кадрах? :)

Добавлено через 2 минуты
Можно еще так:
Код AS3:

var i:int = container.numChildren;
while (i--)
    container.removeChildAt(i);


etc 28.08.2011 13:05

Самый быстрый, как ни странно, while (map_layer.numChildren) map_layer.removeChildAt(0);.

Aquahawk 28.08.2011 13:48

Цитата:

Сообщение от i.o. (Сообщение 1026172)
Можно еще так:
Код AS3:

var i:int = container.numChildren;
while (i--)
    container.removeChildAt(i);


Нельзя так. Например может быть дисплейобджект, который на свой ремув утащит ещё что-нибудь с парента. У меня так текстфилды с кастомный бекграундом сделаны. Класс наследник текстфилда не может сделать addchild на себя. А нужен хитрый динамический фон. Для этого он на своём событии added на парента складывает бекграунд и свапается с ним, а на ремувед, удаляет свой бекграунд сам. Такми образом это внешне текстфилд и весь код который работает с текстфилдом, работает и с ним, а уже он сам за собой таскает свой фон.(естественно переопределены сеттеры размеров и координат). Так вот когда сремувится текстфилд, он ремувит фон, и приведённый код выпадет с ошибкой.

etc 28.08.2011 13:52

Цитата:

Сообщение от Aquahawk (Сообщение 1026187)
может быть дисплейобджект, который на свой ремув утащит ещё что-нибудь с парента.

Это называется плохо спроектированный код. В вашем случае конечно так нельзя. Но это только в вашем случае.

i.o. 28.08.2011 13:58

Цитата:

Нельзя так
Ну тогда:
Код AS3:

while (container.numChildren)
    container.removeChildAt(container.numChildren - 1);


Aquahawk 28.08.2011 14:02

Цитата:

Сообщение от etc (Сообщение 1026188)
Это называется плохо спроектированный код. В вашем случае конечно так нельзя. Но это только в вашем случае.

Я достаточно долго обдумывал как наиболее аккуратно сделать такие текстфилды. К моему сожалению текстфилд не является DisplayObjectContainer и на него ничего повесить нельзя. В данной задаче уже была тьма кода который работал с кучей текстфилдов, и надо было минимальной кровью дать им поддержку бекграундов. Я вижу тут только два варианта, либо делать наследника спрайта, и на него уже складывать текстфилд, либо делать так как я описал. Если делать спрайт, то он уже не будет являться текстфилдом, и все функции которые с ним работают придётся переделать.

В то-же время приведённый вами while (map_layer.numChildren) map_layer.removeChildAt(0); работает абсолютно корректно, и является более правильным способом удалить всех чайлдов. Т.к. событие removed может обрабатываться и каждый раз, когда вы пишете map_layer.removeChildAt(0) может выполняться сторонний код, который может изменять число чайлдов.

Между условиями "Удалим столько детей сколько их было в начале операции" и "Удаляем пока их совсем не останется" есть большая разница.

i.o. 28.08.2011 14:05

Цитата:

У меня так текстфилды с кастомный бекграундом сделаны. Класс наследник текстфилда не может сделать addchild на себя. А нужен хитрый динамический фон.
Что вам мешало создать своеобразный компонент?
Компонент - контейнер (наследник от DisplayObjectContainer), содержащий фон и обычный текстфилд.

Aquahawk 28.08.2011 14:05

Правда если кто-то особо злой на ремуве будет добавлять себя на место, можно и зависнуть. В моём случае на ремуве ещё один ремув, я думаю что это корректно, хотя и не красиво.

Добавлено через 37 секунд
Цитата:

Сообщение от i.o. (Сообщение 1026192)
Что вам мешало создать своеобразный компонент?
Компонент - контейнер (наследник от DisplayObjectContainer), содержащий фон и обычный текстфилд.

Выше уже написал.

etc 28.08.2011 14:10

Ничего не мешает сделать текстфилд торчащим наружу ссылкой :)

i.o. 28.08.2011 14:10

Цитата:

Выше уже написал.
Все равно неубедительно.
Ваш расширенный TextField прикладывает руки к своему родителю и ковыряется в его детях. При этом вам еще необходимо подписываться/отписываться от событий ADDED/REMOVED.
Не самый лучший вариант на мой взгляд.

-De- 28.08.2011 14:13

Можно сделать полем вашего текстфилда спрайт. В который добавлять сам этот текстфилд и фон. Всё это делать и вообще создавать спрайт можно только если нужен навороченный фон. Ну там ещё перегрузить addChild/removeChild. Будут иногда некоторые проблемы, если этот текстфилд достается при помощи getChildByName/getChildAt, ну так не юзать их лишний раз, они вот точно зло =)

Aquahawk 28.08.2011 14:23

Решение -De- интересно, но всё равно не позволяет просто заменить new TextField() на фабрику и забыть. Моё позволяет. Мне оно самому не нравится тем, что лазит в парента, и я с радостью его переделаю на более адекватное, но пока таковых не нашёл.


Часовой пояс GMT +4, время: 00:29.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.