ломается Tree

4 views
Skip to first unread message

Shaman

unread,
Nov 3, 2009, 8:49:16 AM11/3/09
to ruf...@googlegroups.com
Компонент Tree с кастомным итем рендерером  при мануальном скролировании со статическими данными отрисовывается хорошо. Если данные динамические (XML как дата провайдер) , после открытие ветки начинает неправильно все отрисовываться, выглядит так, как будто чилдрены меняют родителя.

[code]
package
{
   
    import mx.controls.treeClasses.TreeItemRenderer;

    public class TaggedMapTreeItemRenderer extends TreeItemRenderer
    {
       
        public function TaggedMapTreeItemRenderer()
        {
            super();
        }
        override public function set data(value:Object):void
        {
            if(value != null)
            {
                super.data = value;
            }
         }     

        override protected function commitProperties():void
        {
            super.commitProperties();
            label.text = data ? data.@name : "";
            if (label.text.length > 15 )
            {
                label.text = label.text.substr(0,15)+"...";
            }
           
        }
    }
}
[/code]

Если кто сталкивался с таким странным поведением, нид хелп.

--
Pavel.

Roman Malko

unread,
Nov 3, 2009, 9:13:26 AM11/3/09
to ruFlex
Не знаю, поможет ли совет, но, в оверрайденом сеттерне даты делать так
нельзя. Ибо если value будет нул, то commitProperties вообще не
вызовется.

kubanoid

unread,
Nov 5, 2009, 6:54:33 AM11/5/09
to ruFlex
Чилдрены меняют родителя. Именно так и есть. Я в своё время сломал об
это голову. Но спасибо, нашёлся человек поумнее меня - подсказал. К
сожалению, сейчас не могу привести пример кода - где код и где я =)
Происходит там следующее - при отрисовке дерева создаётся пул
рендереров, которые могут добавляться либо удаляться в/из дисплей-
листа. Это позволяет не создавать количество рендереров по количеству
узлов датапровайдера дерева (их может быть очень много), а обходиться
количеством рендереров, достаточным для отображения дерева. Такая
своеобразная система кэширования.
Так, вот проблема в том, что, например при открытии узла, а чаще всего
при скролле дерева, то есть в том момент, когда дерево работает с
пулом рендереров, рендереры могут меняются из пула в дисплей-лист и
обратно, а вот свойство data остаётся к ним прибиндено наглухо. Помню,
мы решили это с помощью BindingUtils, bind, unbind, changeWatcher,
точнее сейчас не вспомню.
Message has been deleted

Андрей Скорик

unread,
Nov 5, 2009, 9:34:24 AM11/5/09
to ruf...@googlegroups.com
> Аааааа что же делать, что же делать.....

1. не пугаться
2. читать про itemRenderers
3. :) не верить без проверки всему что говорят


--
С уважением, Скорик Андрей. andrew...@gmail.com

Roman Malko

unread,
Nov 5, 2009, 9:58:50 AM11/5/09
to ruFlex
А может подписаться на респонс от сервера как только нвоый xml пришел,
и сетать его вручную?

И что значит *чилдрены меняют родителя*? Чилдрены кого?

> С уважением, Скорик Андрей. andrewsko...@gmail.com

Андрей Скорик

unread,
Nov 5, 2009, 10:07:41 AM11/5/09
to ruf...@googlegroups.com
причина ваших бед в неправильной инвалидации САМОГО рендерера. он не
инвалидируется и не коммитит свойства.

label.text = data ? data.@name : "";

имя атрибута должно задаваться в labelFunction у Tree

-------

label.text = label.text.substr(0,15)+"...";

а это лучше делать в measure
------

а так же советую посмотреть как устроен commit в том классе от
которого вы отнаследовались


if (_data != null)
{
listOwner = Tree(_listData.owner);

if (_listData.disclosureIcon)
{
var disclosureIconClass:Class = _listData.disclosureIcon;
var disclosureInstance:* = new disclosureIconClass();

// If not already an interactive object, then we'll wrap
// in one so we can dispatch mouse events.
if (!(disclosureInstance is InteractiveObject))
{
var wrapper:SpriteAsset = new SpriteAsset();
wrapper.addChild(disclosureInstance as DisplayObject);
disclosureIcon = wrapper as IFlexDisplayObject;
}
else
{
disclosureIcon = disclosureInstance;
}

addChild(disclosureIcon as DisplayObject);
disclosureIcon.addEventListener(MouseEvent.MOUSE_DOWN,
disclosureMouseDownHandler);
}

if (_listData.icon)
{
var iconClass:Class = _listData.icon;
icon = new iconClass();

addChild(DisplayObject(icon));
}

label.text = _listData.label;
label.multiline = listOwner.variableRowHeight;
label.wordWrap = listOwner.wordWrap;
}
else
{
label.text = " ";
toolTip = null;
}


как это видно без микроскопа данные берутся из listData - как вы
думаете с чего бы это? :)


и никаких BindingUtils :))))

Shaman

unread,
Nov 6, 2009, 7:29:32 AM11/6/09
to ruf...@googlegroups.com


как это видно без микроскопа данные берутся из listData - как вы
думаете с чего бы это? :)

Этой listData можно манипулировать? Или что с ней можно сделать, я честно не понял.


--
Pavel.

Shaman

unread,
Nov 6, 2009, 7:58:45 AM11/6/09
to ruf...@googlegroups.com

И что значит *чилдрены меняют родителя*? Чилдрены кого?

Визуально так выглядит что отображаемые итемРендеры как чилдрены пргают от одного визуального парента к другому.

--
Pavel.

Roman Malko

unread,
Nov 6, 2009, 8:16:42 AM11/6/09
to ruFlex
АйтемРендереры должны удалять инфу, которая была до этого!

То есть, если ты хочешь лист с 8 строчками, тогда Лист создает 8
рендереров + 2 или 3 для кеша. Если у тебя датапровайдер имеет 100
записей, то для этих ста записей лист не создает столько-же
рендереров. Он создает 8 + 2, и, сетает data айтемрендереру объекты из
массива от 0 до 10.

Если ты скролишь, то он просто сетает инфу этим-же рендерерам.
Поэтому, нужно удалять любые исторические записи от предыдущих
объектов.

Вот отличная статься - http://www.adobe.com/devnet/flex/articles/itemrenderers_pt5.html

Roman Malko

unread,
Nov 6, 2009, 8:17:41 AM11/6/09
to ruFlex
Добавлю, что айтемрендереры не двигаются вовсе!

On 6 ноя, 14:58, Shaman <shama...@gmail.com> wrote:

Message has been deleted

Андрей Скорик

unread,
Nov 9, 2009, 4:13:48 AM11/9/09
to ruf...@googlegroups.com
> Добавлю, что айтемрендереры не двигаются вовсе!
>

не совсем так. лист устроен так что при скроле на небольшие расстояния
двигаются те же самые итем рендереры и им переназначаются данные. а
если лист отскролили сразу на большое расстояние - рендереры
уничтожаются и создаются заново.

>
> Этой listData можно манипулировать? Или что с ней можно сделать, я честно не понял.
>

смотрите референс по классу BaseListData. вы там можете получить
индекс ряда (и колонки для датагрида) и ссылку на родительский
компонент и взять нужные данные из его датапровайдера.
--
С уважением, Скорик Андрей. andrew...@gmail.com

Ilja Panin

unread,
Nov 9, 2009, 4:40:56 AM11/9/09
to ruf...@googlegroups.com
> а
> если лист отскролили сразу на большое расстояние - рендереры
> уничтожаются и создаются заново.
>

Ну и чтобы сразу избежать недоразумений. Рендеры не уничтожаются, а
"складываються на полочку", а потом по мере надобности, беруться с нее
и им проставляются новая data.
И насколько мне помниться при складывании на полочку у них даже не
чистится пропертя data

--
Ilja Panin
http://the33cows.com

Shaman

unread,
Nov 9, 2009, 8:00:29 AM11/9/09
to ruf...@googlegroups.com
Как оказалось все портило некорректное (по мнению компонента Tree) заполнение чилдренов в датапровайдере. Если назначать сразу все чилдрены setChildren , то все ломалось, если делать appendChild -- работает.


--
Pavel.
Reply all
Reply to author
Forward
0 new messages