Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Вопрос: удаление всех Child из родительского мувика. (http://www.flasher.ru/forum/showthread.php?t=108958)

Azim 04.03.2008 13:35

Вопрос: удаление всех Child из родительского мувика.
 
Перевожу прогу AS2->AS3.

Проблема:
Есть top:MovieClip - родительский.
В нем создаю через new MovieClip и addChild еще мувики (программно создаю).
Есть кнопка очистки родительского мувика. Алгоритм чистки следующий:
function clearTop(){
for(var i:Number = 1; i<=top.numChildren; i++){
if(top.getChildAt(i)){
top.removeChildAt(i);
}
}
}
Алгоритм работает один раз - чистит содержимое top, а на второй раз - ругается что нет нифига - ругается 2006 ошибкой, типа нет мувика с таким индексом. Хотя проверку я поставил.

Как сделать корректную проверку на существование Child?

Замена top.getChildAt(i) на Boolean(top.getChildAt(i)) - ничего не дала

BlooDHounD 04.03.2008 13:52

Ошибки:
1. индексы детей начинаются с 0.
2.
Код:

if(top.getChildAt(i)){
top.removeChildAt(i);
}

код бесмысленен. в АС3 не бывает пустых пространств между детьми. удаляя одно дитя, все кто сидел выше смещаются вниз.
3.
Код:

for(var i:Number = 1; i<=top.numChildren; i++){...
по причине описанный в п.2, у вас вообще получается обсурд. с каждым удалёнием numChildren уменьшается на 1. и при этом вы удаляете i-тый элемент.

вот ваш алгаритм:

Код:

start.    1.        2.        3.
0 - A      0 - A      0 - A      0 - A
1 - B      1 - C      1 - C      1 - C
2 - C      2 - D      2 - E      2 - E
3 - D      3 - E      3 - F
4 - E      4 - F
5 - F


Azim 04.03.2008 14:54

Обалдеть! А как тогда правильно удалить всех детей родительского мува?

Mr. Fixit 04.03.2008 15:00

или так:
Код:

while(this.numChildern > 0) this.removeChildAt(0);
или так:
Код:

for(var i : int = 0; i < this.numChildern; i++) this.removeChildAt(0);
или так:
Код:

for(var i : int = this.numChildern-1; i >= 0 ; i--) this.removeChildAt(this.numChildern-1);
или еще как-то :D

BlooDHounD 04.03.2008 15:03

или так:
Код:

var num:int = super.numChildren;
while ((num -= 1)>0) super.removeChildAt(num);


Azim 04.03.2008 15:05

Парни! Идеально! Спасибо!!
Недопетривал стековость контейнера. Теперь вообще многое прояснилось)))

Бармалей 04.03.2008 16:46

Маленькая лепта от меня:
Код:

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

Удалять элементы с нулевой глубины - труднозатратно, поскольку элементы следующие за удаленным будут сдвинуты на единицу вниз. Представьте, если в контейнере содержатся несколько тысяч чайлдов.

BlooDHounD 04.03.2008 17:17

ну если на то пошло то numChildren тоже жрёт ресурсы.

Бармалей 04.03.2008 17:33

Ну я не спорю, только почему-то мне кажется, что numChildren кэшируется при изменении количества детей и возвращается по требованию, а не пересчитывается каждый раз при обращении к нему. ;-)

_Smirnoff 04.03.2008 17:48

Узнайте кол-во детей один раз...и удаляйте относительно него + лучше удалать, начиная с верхних, чтоб не менять индексы слоев при удалении.

BlooDHounD 04.03.2008 17:52

Цитата:

Сообщение от Бармалей
Ну я не спорю, только почему-то мне кажется, что numChildren кэшируется при изменении количества детей и возвращается по требованию, а не пересчитывается каждый раз при обращении к нему. ;-)

ага ... может конечно и не считает, но скорости постоянное обращение к гетору не прибовляет. это таже история что и length у массива.

Бармалей 04.03.2008 18:22

Цитата:

Сообщение от BlooDHounD
ага ... может конечно и не считает, но скорости постоянное обращение к гетору не прибовляет. это таже история что и length у массива.

Хорошо, дубль два в три строки:
Код:

var num:uint = container.numChildren;
while(num--)
        container.removeChildAt(num);

=)

BlooDHounD 04.03.2008 18:28

-- работает гараздо медлее чем -=. и теперь глянь на код, который я написал

Бармалей 04.03.2008 18:54

Цитата:

Сообщение от BlooDHounD
-- работает гараздо медлее чем -=. и теперь глянь на код, который я написал

Рабочая машина. Flash Player WIN 9,0,115,0. Импорты пропущены.

Обратный инкремент с автоматическим приведением типов:
Код:

var t:int = getTimer();
var i:uint = 10000000;
while(i--){}
trace(getTimer() - t); // 181

Оператор вычитания с присваиванием и явным приведением типов:
Код:

var t:int = getTimer();
var i:uint = 10000000;
while((i -= 1)>0){}
trace(getTimer() - t); // 235

Статья годовалой давности про медленный инкремент видимо уже не актуальна в последних сборках проигрывателя. Хотя проигрыш в 54 миллисекунды при обсчете 10 миллионов операций не будет особенно заметен - основное время будет тратиться именно на очистку дисплей листа виртуальной машиной. Но "дубль два" все таки рулит. =)

BlooDHounD 04.03.2008 19:12

и что? это доказывает мою правоту.

Бармалей 04.03.2008 19:15

Почему? Наоборот: предложенный мной вариант выполнился за 181 миллисекунду, а предложенный тобой - за 235.

etc 04.03.2008 19:39

Azim, отредактируйте свой первый пост и оформите код тегами [code][/code].

з.Ы.
Код:

var t:int = getTimer();
var i:uint;
for (i = 10000000;i>0;i--){};
trace(getTimer() - t); // 235
t = getTimer();
for (i = 10000000;i>0;i-=1){};
trace(getTimer() - t); // 56


Бармалей 04.03.2008 20:07

Выносим инициализацию переменной i до таймера, и видим немного другие результаты =)
Код:

var i:uint;
var t:int = getTimer();
for (i = 10000000;i>0;i--){};
trace(getTimer() - t); // 41
t = getTimer();
for (i = 10000000;i>0;i-=1){};
trace(getTimer() - t); // 41


Iv 04.03.2008 20:15

BlooDHounD, Бармалей: вы потратили машинного времени на обсуждение этой ерунды больше, чем все флэшеры мира сэкономят на таких итерациях за последующие 50 лет.

Бармалей 04.03.2008 20:16

Цитата:

Сообщение от Iv
BlooDHounD, Бармалей: вы потратили машинного времени на обсуждение этой ерунды больше, чем все флэшеры мира сэкономят на таких итерациях за последующие 50 лет.

Iv, зато теперь мы знаем Кунг-Фу на AS3. =)

badun 04.03.2008 21:58

Цитата:

Сообщение от Бармалей
Выносим инициализацию переменной i до таймера, и видим немного другие результаты =)
Код:

var i:uint;
var t:int = getTimer();
for (i = 10000000;i>0;i--){};
trace(getTimer() - t); // 41
t = getTimer();
for (i = 10000000;i>0;i-=1){};
trace(getTimer() - t); // 41


Запустил код, у меня выдало:
//200
//54
соответственно

Еще не совсем понял из каких соображений переменная i типа uint, а не int. Для int у меня выдало:
//66
//48

WindWalker 04.03.2008 22:08

Цитата:

Сообщение от badun
запустил код, у меня выдало
200
54
соответственно

Добавьте ещё в конце:
Код:

trace (flash.system.Capabilities.version);
Подозреваю, что выдаст 9,0,45,0

badun 04.03.2008 22:14

WIN 9,0,115,0

etc 05.03.2008 00:23

Цитата:

Сообщение от Бармалей
Выносим инициализацию переменной i до таймера, и видим немного другие результаты =)
Код:

var i:uint;
var t:int = getTimer();
for (i = 10000000;i>0;i--){};
trace(getTimer() - t); // 41
t = getTimer();
for (i = 10000000;i>0;i-=1){};
trace(getTimer() - t); // 41


У тебя, значит, уникальный флеш, потому как проверил, для чистоты эксперимернта:
[img]http://img232.**************/img232/7006/speeded9.png[/img]
Код:

txt.text = Capabilities.version+"\n";
var i:uint;
var t:int = getTimer();
for (i = 10000000;i>0;i--){};
txt.appendText((getTimer() - t)+"\n");
t = getTimer();
for (i = 10000000;i>0;i-=1){};
txt.appendText((getTimer() - t)+"\n");

badun, uint из простых соображений, что с числами меньше нуля мы не работаем в цикле.

Бармалей 05.03.2008 00:59

Я заметил только, что имеет значение очередность работы циклов. Если поменять блоки циклов местами, то вот что получится. Хотя, если ничего не трогать, то будет вот так. Предыдущие указанные мною значения были получены при тестировании в FlashDevelop на рабочем компе.

badun 05.03.2008 01:02

to __etc
Так int же не обязывает использовать отрицательные значения. Просто тут обсуждение перешло в область оптимизации, а то что int шустрее чем uint вроде как давно известно. По-этому и не понял зачем оно тут, тем более, что numChildren типа int.

Цитата:

Сообщение от Бармалей
Я заметил только, что имеет значение очередность работы циклов. Если поменять блоки циклов местами, то вот что получится. Хотя, если ничего не трогать, то будет вот так.

Может это не от очередности зависит, а просто расхождения при каждом запуске? Если ничего не менять, значения останутся теми же?

Бармалей 05.03.2008 01:09

В смысле ничего не менять? А как же тогда показать, что первый цикл выполняется медленнее, чем идущий за ним? =)

badun 05.03.2008 01:12

коряво выразился ))
в смысле ничего не менять, и несколько раз запустить и посмотреть какие значения будут выдаваться. Может там +-20 разброс )).

etc 05.03.2008 09:17

Цитата:

Сообщение от Бармалей
Я заметил только, что имеет значение очередность работы циклов.

Поменял местами :)
У меня тенденция не меняется, хоть в разных местах циклы поставь, декремент -=1 всегда быстрее --. Причем разница ощутимая:

[img]http://img216.**************/img216/1510/speedum8.png[/img]

Бармалей 05.03.2008 15:46

Давайте устроим массовую проверку. Вот swf-ка, скомпилированная при помощи Flex 3 SDK. А вот содержимого ее главного класса:
Код:

package
{
        import flash.display.Sprite;
        import flash.text.TextField;
        import flash.utils.getTimer;
        import flash.system.Capabilities;
       
        public class Main extends flash.display.Sprite
        {
               
                protected var textField:TextField;
               
                public function Main():void
                {
                       
                        textField = new TextField();
                        addChild(textField);
                       
                        textField.text = Capabilities.version + "\n";
                       
                        var i:uint;
                        var t:int;
                       
                        t = getTimer();
                        for (i = 10000000;i>0;i--){};
                        textField.appendText((getTimer() - t) + "\n");
                       
                        t = getTimer();
                        for (i = 10000000;i>0;i-=1){};
                        textField.appendText((getTimer() - t) + "\n");
                }
        }
}

А вот код этого же класса, восстановленный декомпилятором из swf:
Код:

package
{
    import Main.*;
    import flash.display.*;
    import flash.system.*;
    import flash.text.*;
    import flash.utils.*;

    public class Main extends Sprite
    {
        var textField:TextField;

        public function Main() : void
        {
1  0 211  1 22            var _loc_1:uint;
            var _loc_2:int;
            textField = new TextField();
            addChild(textField);
            textField.text = Capabilities.version + "\n";
            _loc_2 = getTimer();
            _loc_1 = 10000000;
            while (_loc_1-- > 0)
            {
                // label
            }
            textField.appendText(getTimer() - _loc_2 + "\n");
            _loc_2 = getTimer();
            _loc_1 = 10000000;
            while (_loc_1-- > 0)
            {
                // label
            }
            textField.appendText(getTimer() - _loc_2 + "\n");
            return;
        }
    }
}

Итак, у кого какие значения появляются в текстовом поле при запуске swf. У меня:
Цитата:

WIN 9,0,115,0
38
38
Весьма вероятно, что конструкции i-=1 и i-- компилируются mxmlc, входящим в состав Flex 3 SDK в идентичный байткод. Кстати на днях вышла новая версия Sothink SWF Decompiler, позволяющая декомпилить АС3 код.

etc 05.03.2008 15:58

Значит это особенности компилятора CS3. Вне зависимости от этого, лучше использовать декремент с числом, дабы не получать неожиданных результатов.

etc 05.03.2008 17:46

Повод для размышлений:

Код:

package {
        import flash.display.Sprite;
        import flash.system.Capabilities;
        import flash.text.TextField;
        import flash.utils.getTimer;
       
        public class Main extends Sprite {
               
                private var textField:TextField;
               
                public var i:uint;
               
                public function Main() {
                        super();
                        textField = new TextField();
                        addChild(textField);
                        textField.text = Capabilities.version + "\n";
                        var t:int;
                        t = getTimer();
                        for (i = 10000000;i>0;i-=1){};
                        textField.appendText((getTimer() - t) + "\n");
                        t = getTimer();
                        for (i = 10000000;i>0;i--){};
                        textField.appendText((getTimer() - t) + "\n");
                }
        }
}


_Smirnoff 05.03.2008 18:19

WIN 9,0,115,0
39
45

result такой

Mr. Fixit 05.03.2008 20:45

незабывайте что:
Код:

...
for (i = 10000000;i>0;i-=1){};
textField.appendText((getTimer() - t) + "\n");
t = getTimer();
for (i = 10000000;i>0;i--){};
textField.appendText((getTimer() - t) + "\n");
...

сразу тестить не желательно.. поотдельности даёт более правильный результат.

etc 05.03.2008 22:04

Цитата:

Сообщение от Mr. Fixit
незабывайте что:
Код:

...
for (i = 10000000;i>0;i-=1){};
textField.appendText((getTimer() - t) + "\n");
t = getTimer();
for (i = 10000000;i>0;i--){};
textField.appendText((getTimer() - t) + "\n");
...

сразу тестить не желательно.. поотдельности даёт более правильный результат.

Прежде всего надо знать, во что сей код превращается в CS3.
http://etcs.ru/blog/as3/slow_increment_ii/

Mr. Fixit 05.03.2008 22:32

а причем тут это?
я говорю, что ты сразу считаешь циклы.. потому и нагрузка больше на последний цикл. Проверка циклов поотдельности даст более точный результат, что лучше. Да математика вся не во флеше, а в процессоре.

WindWalker 05.03.2008 22:53

Предполагаю, что инкремент/декремент поля через ++ и -- превращается примерно в такой байткод:

1. взять поле i
2. увеличить
3. записать в поле i
4. взять поле i

И вот этот самый четвёртый пункт всё и портит.

BlooDHounD 05.03.2008 23:23

о, госпади! спаси души этих еретиков!

WindWalker 05.03.2008 23:32

Вот так выглядит i++, если i - это поле:
Код:

findpropstrict        i
dup                 
setlocal1           
getproperty          i
increment           
setlocal2           
getlocal1           
getlocal2           
setproperty          i
kill                  2
kill                  1

А вот так выглядит i+=1:
Код:

findproperty          i
getlex                i
pushbyte              1
add                 
initproperty          i

То есть моё предположение оказалось неверным. Однако лишние манипуляции легко заметны.

etc 05.03.2008 23:55

Цитата:

Сообщение от WindWalker
Однако лишние манипуляции легко заметны.

Само собой, что заметны.
В общем, все всё выяснили, я думаю, вопросов больше возникать не должно.

з.Ы. Походу я отстал от жизни, раз пользуюсь собственным декомпилятором и не знаю о уже существующих :(


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

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