Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Поиск Объектов, по имени, из списка отображения. (http://www.flasher.ru/forum/showthread.php?t=174616)

Vitalya 29.01.2012 19:44

Поиск Объектов, по имени, из списка отображения.
 
Ув. Flash/Flex программисты нужно решить задачу, если у кого есть готовое решение не откажусь.
Насколько я понимаю здесь нужно реализовать обход дерева, пока не найдем нужный DisplayObject...
Я реализовал обход дерева, просто развернув его в Vector, но такой подход медленнее чем РЕКУРСИВНЫЙ.
Да и РЕКУРСИВНЫЙ ПОДХОД ТОЖЕ НЕ КАТИТ((

Вот примерный прототип функции:
public static DisplayObject searchByNameDO( o: DisplayObjectContainer, oname: String ): DisplayObject{
}

silin 29.01.2012 19:59

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

public static function searchByNameDO(o:DisplayObjectContainer, oname:String):DisplayObject
{
        for (var i:int = 0; i < o.numChildren; i++)
        {
                var child:DisplayObject = o.getChildAt(i);
                if (child.name == oname)
                {
                        return child;
                }else if( child  is DisplayObjectContainer)
                {
                        return searchByNameDO(child as DisplayObjectContainer, oname);
                }
        }
        return null;
}


Vitalya 29.01.2012 20:02

Шеф сказал без Рекурсий(( Объяснил мне тем, что нужна скорость больше...
P.S. Согласись неопровержимый факт)

wvxvw 29.01.2012 20:18

Вы столько дисплей объектов не сможете создать, чтобы заметить разницу в скорости работы.
Кроме того, у вас не получится оптимальное решение с циклом, т.как вы не сможете получить списки всех родителей и детей массивом, или какой-то структурой которая сама может запомнить последную позицию перед тем как вы сделали выбор брат/ребенок. Т.е. вам нужно будет куда-то записывать индекс последнего обработанного ребенка для каждого контейнера обрабоку которого вы еще не закончили (вместо того, чтобы хранить это все на стеке).
Конечно, это тяжело говорить шефу, что он ошибается... но задача имеет геометрический смысл, только в случае если это какое-то тестовое задание. А так - глупость.

ChuwY 29.01.2012 20:33

В порядке бреда:
Можно заносить всех детей в нужную вам структуру данных по Event.ADDED, ловящемся на контейнере (корне дерева), например.
Если цепляется лист -- хорошо.
Если цепляется поддерево -- его обходим рекурсивно, но это незначительно при малых поддеревьях.

Vitalya 29.01.2012 20:56

Спасибо, я понимаю что может рекурсия самый оптимальный вариант, но так-как я на испытательном сроке, то что-то доказывать шефу не стану((
Как я в самом начале пытался делать:

getChildByName(name:String):DisplayObject
Возвращает экземпляр дочернего экранного объекта с заданным именем.
1. Прогоняю корень через getChildByName, если результата нет.
2. Иду вниз по всем детям пока не найду нужный либо дерево не закончиться.
!!! Но в процессе реализации запутался очень с тим ДЕРЕВОМ, удалил весь код и написал развертку дерева в Vector и после пробегал по вектору getChildByName-ом. Мне шеф "забанил" работу с вектором, подскажите оптимальный алгоритм пробега по n-арному дереву.

Stitch512 29.01.2012 21:07

Код AS3:

public static function searchByNameDO(owner: DisplayObjectContainer, name: String): DisplayObject
{
        var stackContainers:Vector.<DisplayObjectContainer> = new Vector.<DisplayObjectContainer>();
        var stackIdx:Vector.<int> = new Vector.<int>();
 
        var currContainer:DisplayObjectContainer = owner;
        var idx:int = 0;
 
        while (currContainer != null)
        {
                var result:DisplayObject = currContainer.getChildByName(name);
                if (result != null)
                        return null;
 
                while (idx < currContainer.numChildren)
                {
                        var container:DisplayObjectContainer = currContainer.getChildAt(i)  as DisplayObjectContainer;
                        if (container != null)
                        {
                                stackContainers.push(currContainer);
                                stackIdx.push(idx);
 
                                currContainer = container;
                                idx = 0;
 
                                break;
                        }
 
                        idx++;
              }
 
              currContainer = stackContainers.pop();
              idx = stackIdx.pop();
        }
}

Можно что-то вроде такого. Работоспособность не проверял, но суть в том чтобы вместо использования рекурсии вручную запоминать в переменных стековые значение. Т.е. по факту та же самая рекурсия, но реализованная вручную.

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

!!! Но в процессе реализации запутался очень с тим ДЕРЕВОМ, удалил весь код и написал развертку дерева в Vector и после пробегал по вектору getChildByName-ом. Мне шеф "забанил" работу с вектором, подскажите оптимальный алгоритм пробега по n-арному дереву.
Код AS3:

public static function searchByNameDO(container: DisplayObjectContainer, name: String): DisplayObject
{
        var result:DisplayObject = container.getChildByName(name);
        if (result != null)
                return null;
 
        for (var i:int = 0; i<container.numChildren; i++)
        {
                var childContainer:DisplayObjectContainer = container.getChildAt(i) as DisplayObjectContainer;
                if (childContainer != null)
                {
                        result = searchByNameDO(childContainer);
                        if (result != null)
                                return result;
                }
        }
 
        return null;
}


alatar 29.01.2012 21:27

Насколько часто у вас меняется display list?

Добавлено через 2 минуты
Ну и смысл задачи не ясен. Вам надо найти все DO с определенным именем или только первый.

Vitalya 29.01.2012 21:45

Насчет изменений дисплей листа меня не уведомили, но завтра на месте спрошу. Думаю смысл задачи вернуть хотя-бы первый попавшийся объект с заданным именем, без использования РЕКУРСИИ. Буду благодарен за любые варианты решений!)

Добавлено через 1 час 5 минут
Ув. Stitch512, у меня пару вопросов по исходнику, который не рекурсивный.

Код AS3:

public static function searchByNameDO(owner: DisplayObjectContainer, name: String): DisplayObject
{
        var stackContainers:Vector.<DisplayObjectContainer> = new Vector.<DisplayObjectContainer>();
        var stackIdx:Vector.<int> = new Vector.<int>();
 
        var currContainer:DisplayObjectContainer = owner;
        var idx:int = 0;
 
        while (currContainer != null)
        {
                var result:DisplayObject = currContainer.getChildByName(name);
                if (result != null)
                        return null;//ЗДЕСЬ return result; ???
 
                while (idx < currContainer.numChildren)
                {
                        var container:DisplayObjectContainer = currContainer.getChildAt(i)  as DisplayObjectContainer;
                        //ЗДЕСЬ вместо i - idx или просто наращивать i ниже?
                        if (container != null)
                        {
                                stackContainers.push(currContainer);
                                stackIdx.push(idx);
 
                                currContainer = container;
                                idx = 0;
 
                                break;
                        }
 
                        idx++;
              }
 
              currContainer = stackContainers.pop();//Что здесь происходит?
              idx = stackIdx.pop();//Что здесь происходит?
        }
        return null;
}

Заранее благодарен за ответ!)

alatar 29.01.2012 23:13

Вот вам без рекурсии.
Код AS3:

private const objectsMap:Object = {};
...
stage.addEventListener(Event.ADDED_TO_STAGE, stage_addedToStagehandler, true);
stage.addEventListener(Event.REMOVED_FROM_STAGE, stage_removedToStagehandler, true);
...
protected function stage_removedToStagehandler(event:Event):void
{
    objectsMap[event.target.name] = event.target;
 
}
protected function stage_addedToStagehandler(event:Event):void
{
    delete objectsMap[event.target.name];
}
 
private function searchByName(name:String):DisplayObject
{
    return objectsMap[name];
}

Но, возвращать будет всегда последний добавленный в список отображения объект с именем name, а удалять его будет как только будет удален, хотя бы один объект с именем name. Думаю догадаетесь как это обойти. Ну и name у объектов меняться не должен, иначе будут утечки (для своих объектов это решаемо).


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

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