Why does updateDisplayList stop happening in Flex? - apache-flex

Reward: Has been claimed.
Overview: The code giving me the problem is deployed here: http://www.johnuckele.com/MastersOfTime.html
The problem I am running into is that a certain sequence of actions (I don't fully understand how or why) is causing my calls to invalidateDisplayList to fail to produce a subsequent call to updateDisplayList. What I know is that during this period, some other visual effects will fail to occur (such as changing the width of a component or the addition of a new child).
Example: The program below draws two columns of horizontal lines. The column on the left is drawn during commitProperties, the column on the right is drawn during updateDisplayList. A certain sequence of actions can cause the right column to stop updating.
To trigger this bug: First add a new item. Now hit the start button and a bar starts filling up. If you press the add row button, the right column and the filling bar both stop growing. The left column continues unfettered. The extra component won't appear until the last line of the if statement in TEComputeRow.tick() doesn't execute for a frame. Click on the stop button to halt the execution of the block inside the if statement in TEComputeRow.tick() and everything goes back to normal.
Question: What is going on here?
I can force it to behave by using validate now but it doesn't cure the problem, it merely covers it up for a frame. It also seems like a really sloppy hack. Is there a nicer way to deal with the loss of updateDisplayList than using validateNow? Are there any ways to accurately identify the state of the world?
MastersOfTime.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
backgroundColor="white"
backgroundGradientAlphas="[1,1]"
initialize="init()"
enterFrame="tick()"
creationComplete="addComputeArray()">
<mx:Script>
<![CDATA[
import mx.containers.HBox;
import mx.controls.Button;
import mx.containers.VBox;
import flash.utils.getTimer;
private var global:int = 0;
private function addComputeArray():void
{
var addButton:Button = new Button;
addButton.label = "Add Row Item";
addButton.addEventListener(MouseEvent.CLICK, addComputeBox);
box.addChild(addButton);
}
private function addComputeBox(a:* = null):void
{
box.addChild(new TEComputeRow());
}
private function init():void
{
box.clipContent = false;
box.graphics.lineStyle(1);
}
private function tick():void
{
global++;
this.invalidateDisplayList();
this.invalidateProperties();
//this.validateNow();
}
protected override function commitProperties():void
{
super.commitProperties();
box.graphics.moveTo(100, (global*3)%800);
box.graphics.lineTo(200, (global*3)%800);
}
protected override function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
box.graphics.moveTo(200, (global*3)%800);
box.graphics.lineTo(300, (global*3)%800);
}
]]>
</mx:Script>
<mx:VBox id="box"/>
</mx:Application>
TEComputeRow.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
height="60"
width="352"
verticalGap="0"
borderStyle="solid"
enterFrame="tick()">
<mx:Script>
<![CDATA[
public var doStuff:Boolean = false;
private var parameter:Number = 0;
private function tick(e:Event = null):void
{
var value:*;
if(doStuff)
{
parameter = parameter+1;
value = parameter;
fill.width = value;
}
}
]]>
</mx:Script>
<mx:Button label="turn on" click="{doStuff = true;}" height="20"/>
<mx:Container id="fill" x="7" width="0" height="20" backgroundColor="0x8888AA"/>
<mx:Button label="turn off" click="{doStuff = false;}" height="20"/>
</mx:VBox>

Well for starters, you are abusing the Flex life-cycle horribly, and doing things you are not meant to do... Changing the width of the fill in the tick of the row kicks off another invalidation cycle is the one that immediately jumps out. If you drove things via the Timer rather than on enterFrame, you'd immediately be better off.
My guess is that you spend so much time per frame re-invalidating the properties (changing the width will invalidate properties), the player never fits in the updateDisplayList.
Read up on both the elastic race track, and Deepa's presentation on the Flex 3 lifecycle.

The use of .width is what is triggering this problem. If I replace .width with .setActualSize the problem stops. These pieces of code travel through separate paths and .width and .height apparently have the capacity to skip part of the frame cycle (the updateDisplayList part).

Related

Handling mouse click in Flex 4 List to find the selected item (since itemClick is gone)

I have prepared a simplified test case for my question. It will run instantly in your Flash Builder if you put the 2 files below into a project.
I'm trying to display a List of strings and a confirmation checkbox in a popup:
In the real application I dispatch a custom event with the string selected in the list, but in the test code below I just call trace(str);
My problem: if I use click event, then the window closes, even if I click at a scrollbar (the !str check below doesn't help, when an item had been selected in previous use). And if I use change event, then the window doesn't close, when I click on the same item as the last time. And the itemClick event seems not to be present in spark.components.List anymore.
Any suggestions please on how to handle this probably frequent problem?
Writing a custom item renderer and having a click event handler for each item seems to be overkill for this case, because I have strings in the list.
Test.mxml: (please click myBtn few times - to see my problems with click and change)
<?xml version="1.0" encoding="utf-8"?>
<s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
minWidth="400" minHeight="300">
<fx:Script>
<![CDATA[
import mx.managers.PopUpManager;
private var _popup:Popup = new Popup();
private function showPopup(event:MouseEvent):void {
PopUpManager.addPopUp(_popup, this, true);
PopUpManager.centerPopUp(_popup);
}
]]>
</fx:Script>
<s:Button id="myBtn" right="5" bottom="5"
label="Open window" click="showPopup(event)" />
</s:Application>
Popup.mxml:
<?xml version="1.0" encoding="utf-8"?>
<s:TitleWindow
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="240" height="240"
creationComplete="init(event)"
close="close()">
<fx:Script>
<![CDATA[
import mx.collections.ArrayList;
import mx.controls.Alert;
import mx.events.FlexEvent;
import mx.events.CloseEvent;
import mx.events.ItemClickEvent;
import mx.managers.PopUpManager;
private var myData:ArrayList = new ArrayList();
private function init(event:FlexEvent):void {
// XXX in the real app data is updated from server
myData.removeAll();
for (var i:uint = 1; i <= 10; i++)
myData.addItem('Item #' + i);
}
public function close(event:TimerEvent=null):void {
PopUpManager.removePopUp(this);
}
private function handleClick(event:MouseEvent):void {
var str:String = myList.selectedItem as String;
if (!str)
return;
if (myBox.selected) {
Alert.show(
'Select ' + str + '?',
null,
mx.controls.Alert.YES | mx.controls.Alert.NO,
null,
handleConfirm,
null,
mx.controls.Alert.NO
);
} else {
sendEvent();
}
}
private function handleConfirm(event:CloseEvent):void {
if (event.detail == mx.controls.Alert.YES)
sendEvent();
}
private function sendEvent():void {
close();
// XXX in the real app dispatchEvent() is called
trace('selected: ' + (myList.selectedItem as String));
}
]]>
</fx:Script>
<s:VGroup paddingLeft="20" paddingTop="20"
paddingRight="20" paddingBottom="20" gap="20"
width="100%" height="100%">
<s:List id="myList" dataProvider="{myData}"
click="handleClick(event)"
width="100%" height="100%" fontSize="24" />
<s:CheckBox id="myBox" label="Confirm" />
</s:VGroup>
</s:TitleWindow>
Also I wonder, why do I get the warning above:
Data binding will not be able to detect assignments to "myData".
The Spark List dispatches an 'IndexChangeEvent.CHANGE'. You can listen for this event to know when the selection in the List has changed.
<s:List id="myList" dataProvider="{myData}"
change="handleIndexChange()"
width="100%" height="100%" fontSize="24" />
That event is only dispatched whenever the selected index actually changes, which means that when you reopen the window a second time an item might still be selected and when you click on that one, no CHANGE event will be fired. To fix this just deselect the selection before you close the window:
public function close():void {
myList.selectedIndex = -1;
PopUpManager.removePopUp(this);
}
Also make sure to dispatch your event with the selected item before you close the window (and deselect it).
As for your question about the binding warning: you get that message because you didn't mark 'myData' to be bindable. To fix this just use the [Bindable] tag:
[Bindable]
private var myData:ArrayList = new ArrayList();
or skip the binding altogether if you don't need it and just assign the dataprovider to the list in ActionScript:
myList.dataProvider = myData;
I'd recommend two solutions if you absolutely wnat to display what item was selected. Otherwise, the solution provided by RIAStar would do the trick.
Listen to rendererAdd and rendererRemove events within your PopUp
As explained here, you can easily access to your list's renderers without interfering with its virtualLayout business.
Use a custom renderer
I know. But as long as you keep your code clean, itemRenderers won't blow up your application's memory. They're made to render huge amount of items without memory leaks.
In your Test.mxml, modify the codes like:
<fx:Script>
<![CDATA[
import mx.managers.PopUpManager;
private var _popup:Popup;
private function showPopup(event:MouseEvent):void {
_popup = new Popup();
PopUpManager.addPopUp(_popup, this, true);
PopUpManager.centerPopUp(_popup);
}
]]>
</fx:Script>
And in your Popup.mxml, I am not sure why you have the TimerEvent in the close function.
Also the trace won't be shown, as you are calling the close() function immediately after the alert's YES button has been clicked..

measure various phases of code execution

Is there a way to measure the average time it takes my code to run and each frame to render for my Flex app? More specifically, I know how to use getTimer() but I'm not sure about which events I should listen to in order to do this. I was reading this post and am not sure how you'd figure out how long the actual rendering took (it would seem like it may be the time between the RENDER event fires and the next ENTER_FRAME event fires, but I'm not sure). Also, not exactly sure where the user code happens, or whether I should care about EXIT_FRAME and FRAME_CONSTRUCTED.
Any help much appreciated!
EDIT ----
here's a snippet of code showing the main events for each repetition of the second frame in a super simple flex app. What I'm trying to figure out is whether there is a clear relationship between the "user code" and "rendering" parts of the classic Flex racetrack and the intervals between the four main signals that I'm tracing from.
The code:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Script>
<![CDATA[
import flash.utils.getTimer;
public var t:Timer;
protected function button1_clickHandler(event:MouseEvent):void
{
t = new Timer(40, 50);
t.addEventListener(TimerEvent.TIMER, handleTimeTick);
t.addEventListener(TimerEvent.TIMER_COMPLETE, timerDone);
addEventListener(Event.RENDER, application1_renderHandler);
addEventListener(Event.ENTER_FRAME, application1_enterFrameHandler);
addEventListener(Event.EXIT_FRAME, application1_exitFrameHandler);
addEventListener(Event.FRAME_CONSTRUCTED, application1_frameConstructedHandler);
t.start();
}
protected function handleTimeTick(e:TimerEvent):void
{
shape.x += 5;
}
protected function timerDone(e:TimerEvent):void
{
t.stop();
t.removeEventListener(TimerEvent.TIMER, handleTimeTick);
t.removeEventListener(TimerEvent.TIMER_COMPLETE, timerDone);
removeEventListener(Event.RENDER, application1_renderHandler);
removeEventListener(Event.ENTER_FRAME, application1_enterFrameHandler);
removeEventListener(Event.EXIT_FRAME, application1_exitFrameHandler);
removeEventListener(Event.FRAME_CONSTRUCTED, application1_frameConstructedHandler);
}
protected function application1_renderHandler(event:Event):void
{
trace("render fire", getTimer());
}
protected function application1_enterFrameHandler(event:Event):void
{
trace("enter frame fire", getTimer());
}
protected function application1_exitFrameHandler(event:Event):void
{
trace("exit frame fire", getTimer());
}
protected function application1_frameConstructedHandler(event:Event):void
{
trace("frame constructed fire", getTimer());
}
]]>
</fx:Script>
<s:Rect id="shape" x="0" y="0" height="20" width="20">
<s:fill>
<s:SolidColor color="0xff0000"/>
</s:fill>
</s:Rect>
<s:Button x="10" y="100" click="button1_clickHandler(event)" label="go"/>
</s:Application>
Easy way to test out the time to takes for a "frame" to run. Here's a quick example. This is untested but you get the idea. You should also look at Grant Skinners talk about performance and framerates.
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:parsley="http://www.spicefactory.org/parsley"
creationComplete="onCreationComplete()">
<fx:Script>
<![CDATA[
private var _timer:Timer = new Timer(1000);
private var _previousTime:int;
private var _avgTime:int;
private var _times:Array = [];
private function onCreationComplete():void
{
// Add event listener for enter frame
this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
// Listen to timer
this._timer.addEventListener(TimerEvent.TIMER, onTimer);
// start timer
this._timer.start();
}
private function onEnterFrame(e:Event):void
{
var time:int = getTimer() - this._previousTime;
trace("timer frame took "+ time +"ms");
this._previousTime = getTimer();
this._times.push(time);
}
private function onTimer(e:Event):void
{
var total:int = 0;
for(var i:uint = 0, len:uint = this._times.length; i < len ; i++)
{
total += this._times[i];
}
this._avgTime = total/len;
this._times = [];
trace("Average frame time is "+ this._avgTime +"ms");
}
]]>
</fx:Script>
</s:Application>
Any Flex app is only two frames. The first frame is the startup/initialization of the framework and the second frame is your app.
The framerate is set on the Flex Application tag and the default is 24 frames per second. So, therefore it takes Flex 1/24 of a second to render the frames of your application.
However, it is entirely probably that your code takes more than one frame to execute, and I believe that is what you want to measure.
For some background reading, you should investigate the Flex Elastic Racetrack about how Flex divides each frame for different types of processing.
Then read up, if you haven't already, about the Flex Component LifeCycle. ( Flex 3 Version ) .
You already mentioned the getTimer() method. The gist is to use getTimer() at two points and compare the two values. What those two points are depends entirely on what you want to measure.
If you want to measure the time it takes a Flex component to go through the startup process, use getTimer() before you create it (AKA new Component() ) and then in a listener for that component's creationComplete event.
If you want to time the full application setup, you're best bet is to probably get the value in a preinitialize event handler of the main Application tag and on the applicationComplete handler of the same tag.
Does that help?
Ok, after reading plenty around the web I think this presentation gives the best info about how to measure elastic race track times (see for instance this piece of code from the presentation).

Different tooltips for different parts of a component in Action Script

I want to have a tooltip that shows different things when the mouse goes over a different part of a component. For example if it is the top half of a component it will show one tooltip. If the mouse is on the bottom half of the segment then the tooltip will be another. I have some code I have written that returns a panel with string in. This code is on another computer so I'll post code tomorrow.
Is it possible in ActionScript to have different tooltips (or rather differnt values in a tooltip) for different parts of a segment?
The code I have so far is:
MyToolTip.mxml
<?xml version="1.0"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml"
implements="mx.core.IToolTip"
alpha=".9" width="325" borderColor="black" borderStyle="solid"
cornerRadius="10" horizontalAlign="center">
<mx:Script><![CDATA[
[Bindable]
public var toolTipText:String = "";
public var _text:String;
[Bindable]
public function get text():String { return _text; }
public function set text(value:String):void {}
]]></mx:Script>
<mx:HBox width="100%" height="100%">
<mx:Text text = "Text here" width = "50%"/>
<mx:Text text = "{toolTipText}" width = "50%"/>
</mx:HBox>
</mx:Panel>
And then my action script class component that I want the tooltip to be against.
public class MyComponent extends mx.containers.VBox {
private var tt:MyToolTip
public function MyComponent() {
this.addEventListener(ToolTipEvent.TOOL_TIP_CREATE, toolTipCreateHandler);
this.addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler);
tt = new MyToolTip();
}
override protected function drawFigure():void {
//Need to kick the TOOL_TIP_CREATE event...and needs to be a value (eg a SPACE).
//If blank then no tooltip is created
this.toolTip = " ";
super.drawFigure();
}
private function toolTipCreateHandler(event:ToolTipEvent):void {
var toolTipText:String = "tooltip1";
eventToolTip.toolTipText = toolTipText;
event.toolTip = tt;
}
private function mouseOverHandler(event:MouseEvent):void {
//perhaps I need to be more efficient here and only fire
//when the mouse goes into top half or bottom half
//This does not appear to update the toolTipText in the view
var halfwayUp:Number = getBounds(this).height / 2;
if (event.localY < halfwayUp) {
eventToolTip.toolTipText = "tooltip2";
}
else {
eventToolTip.toolTipText = "tooltip1";
}
}
}
}
Any help or pointers in how to update the tooltip when it is already displaying would be great.
Yes, its possible, the trick is to know how tooltips work:
Tooltips get created, if you mouse over a component, and are destroyed if you mouse out. So if you change the text on a tooltip while its displayed, then you wont see the change, because the set toolTip() function does not creates a new tooltip, if one already exists. So the solution is to destroy the currently showing tooltip, and make a new one. To destroy a tooltip, you can set its value to an empty string.
Here is a sample code:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
mouseMove="application1_mouseMoveHandler(event)">
<mx:Script>
<![CDATA[
import mx.managers.ToolTipManager;
protected function application1_mouseMoveHandler(event:MouseEvent):void{
if (mouseX < 100) {
testButton.toolTip = ""
testButton.toolTip = "on the left side";
} else {
testButton.toolTip = ""
testButton.toolTip = "on the right side";
}
}
]]>
</mx:Script>
<mx:Button id="testButton" label="test" width="200" height="200" />
</mx:Application>
Note: If you want to mess more with tooltips in Flex, you can get the current tooltip with ToolTipManager.currentToolTip (and modify its properties without destroying it).

Flex Cursor management question

I have a spark borderContainer that contains a spark TextInput.
I have an mouse_down and mouse_up event handlers on the borderContainer in order to drag it around the screen; while dragging I change the cursor.
I would like to make the textInput behave as a "standard" textInput, i.e. when clicking on the textInput the user should not be able to drag the whole component but simply interact with text as he/she would normally. Also, I'd like the textInput cursor to look like a normal textInput cursor.
I'm not sure I'm doing this right. My assumption is that I need to stop the propagation of mouse_down and mouse_up on the textInput to inhibit the drag behavior from its parent, and manage rollOver and rollOut in order for the cursor to look ok. See below an example of my code (to simplify it there is no borderContainer or drag - but the code for that would be very simple - just a bit longer).
So here's the issue: if one clicks on the spark textInput and then rolls out of it the cursor turns into a combination of a textInput cursor + the standard cursor set for for the borderContainer. This doesn't seem to happen on mx textInput components (thus the two boxes), but unfortunately I need to use spark components. My guess is that I'm either not calling the cursorManager correctly or I'm not stopping the propagation of mouse_up properly - it seems like it should hit the textInput but not propagate to the borderContainer. I tried stopPropagation() as well but no luck.
Would love any advice / constructive criticism.
thank you!
f
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
creationComplete="application1_creationCompleteHandler(event)"
mouseDown="application1_mouseDownHandler(event)"
mouseUp="application1_mouseUpHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import mx.managers.CursorManager;
[Bindable] [Embed(source="../resources/hand.png")] private var _handIcon:Class;
[Bindable] [Embed(source="../resources/Fist.png")] private var _fistIcon:Class;
private var _cursorID:int;
protected function textinput1_rollOutHandler(e:MouseEvent):void
{
e.stopImmediatePropagation();
CursorManager.removeCursor(_cursorID);
_cursorID = CursorManager.setCursor(_handIcon);
}
protected function textinput1_rollOverHandler(e:MouseEvent):void
{
e.stopImmediatePropagation();
CursorManager.removeCursor(_cursorID);
}
protected function application1_creationCompleteHandler(e:FlexEvent):void
{
_cursorID = CursorManager.setCursor(_handIcon);
}
private function stopPropagation(event:MouseEvent):void
{
event.preventDefault();
event.stopImmediatePropagation();
}
protected function textinput1_mouseDownHandler(event:MouseEvent):void
{
stopPropagation(event);
}
protected function textinput1_mouseUpHandler(event:MouseEvent):void
{
stopPropagation(event);
}
protected function application1_mouseDownHandler(event:MouseEvent):void
{
CursorManager.removeCursor(_cursorID);
_cursorID = CursorManager.setCursor(_fistIcon);
}
protected function application1_mouseUpHandler(event:MouseEvent):void
{
CursorManager.removeCursor(_cursorID);
_cursorID = CursorManager.setCursor(_handIcon);
}
]]>
</fx:Script>
<s:TextInput x="43" y="30"
rollOut="textinput1_rollOutHandler(event)"
rollOver="textinput1_rollOverHandler(event)"
mouseDown="textinput1_mouseDownHandler(event)"
mouseUp="textinput1_mouseUpHandler(event)"/>
<mx:TextInput x="43" y="70"
rollOut="textinput1_rollOutHandler(event)"
rollOver="textinput1_rollOverHandler(event)"
mouseDown="textinput1_mouseDownHandler(event)"
mouseUp="textinput1_mouseUpHandler(event)"/>
You can simply do not start drag and do not change the cursor if user clicks on input:
protected function application1_mouseDownHandler(event:MouseEvent):void
{
var container:DisplayObjectContainer = event.target as DisplayObjectContainer;
if (!container || container == textInput || textInput.contains(container))
return;
// start drag and change the cursor
}
I had a similar problem but I have several TextInput fields in the container. So to avoid checking every single of them I used this version of the idea:
if (event.target is RichEditableText) return;
Works perfectly...
Greetings, J!

Flex: image switching place in tilelist

I'm running into an odd issue with itemRenderers inside a TileList.
Here is a working example without an itemRenderer: 152.org/flex/
Here is the broken version with an itemRenderer: 152.org/brokenExample/
(I don't have the rep to make both of these a link)
Both examples have "View Source" enabled.
To see the problem use the broken example, select an album and scroll down one row. Scroll back up and the images will be switched. If you try this on the working example it's fine.
This seems to be a widely known bug, but I can't find a solution for it.
UPDATE
I started playing with this example again and found out something else. Turns out you don't have to override the data setter. You can create a new method in the itemRenderer that is set whenever the tile wants to refresh. So the trick is to not rely on the initialize or creationComplete methods.
This is what I have for the itemRenderer in the Application.
<itemRenderers:ImageTile img="{data}"/>
This is the code I have in the itemRenderer.
public function set img(value:String) : void {
trace("setting source: " + value);
this.source = value;
this.name = value.toString().split("/").pop().split(".").shift();
}
I updated my example to reflex this change.
I don't have your app handy, so I can't test end-to-end, but I've looked at your source. You probably need to override the data setter in your itemRenderer:
<?xml version="1.0" encoding="utf-8"?>
<mx:Image xmlns:mx="http://www.adobe.com/2006/mxml" initialize="init()">
<mx:Script>
<![CDATA[
override public function set data(value:Object):void
{
super.data = value;
this.source = data;
this.name = data.toString().split("/").pop().split(".").shift();
}
private function init() : void {
// Removed from your source and transplanted above
}
]]>
</mx:Script>
</mx:Image>
Flex will attempt to re-use item renderers in lists (which means the lifecycle events you might be expecting -- initialize, creationComplete, etc. -- won't always fire), so if you want to be sure your renderer gets updated when the data item changes (as it will when scroll events happen), the best practice is to override the renderer's data property. That'll most likely fix the problem.
Maybe try to invalidate on creationComplete?
From what I recall with DataGrids (which work somewhat similarly to a tilelist), when an item comes into focus its recreated.
<mx:itemRenderer>
<mx:Image id="myImage" creationComplete="myImage.invalidate()" />
</mx:itemRenderer>
Haven't tried this code but I think this is where you want to start looking. I took a look at your itemRenderer component. Try creationComplete instead of initialize to call your function

Resources