Flex – dynamic icons on buttons and trees etc
I have had this question asked of me 3 times in as many weeks so I thought it were time to share the answer. The question? In flex when you specify an Icon for a tree or a button etc you are asked to provide type "Class". So you embed your image:
[Embed(source="calendar.gif")]
private var someImage:Class
and then you specify the icon to be:
<mx:Button x="478" y="216"
label="Icon button" icon="{someImage}"/>
you can also specifiy the icons through the style sheet, say referencing an embedded image, but well get to that later.
What the icon property is on most flex controls is of type "Class". This property is a reference the physical class ie "com.xsive.assets.SomeDynamicIconClass".
When the control instanciates itself (creates itself) it checks if the icon property is set, or not null, then creates a new instance of this class, ie:
var icon:Class = new Class();
So after setting my icon="{com.xsive.assets.SomeDynamicIconClass}" the control will actually be calling:
var icon:SomeDynamicIconClass = new SomeDynamicIconClass();
Ok your still with me so lets continue. When you embed an image using:
[Embed(source="calendar.gif")]
private var someImage:Class
the compiler actually turns this into a totally new class which extends the "BitmapAsset" class. This new class on creation has the bitmapdata of the image you embedded. In my test the class name is:
"someImage = ButtonTest_someImage$ (@7ae99c1)"
so when I set icon="{someImage}", I am actually asking the component to create a new ButtonTest_someImage
var icon:ButtonTest_someImage = new ButtonTest_someImage();
and use that the bitmapdata from that as the icon. I hope your still with me and this still reads as english to you.
The big point to get here is that you cant create an instance of a say canvas
var canvas:Canvas = new Canvas();
and convert that instance to a "Class" and give it to a component to use as an Icon, icon=canvas;
This can be very limiting. and to top it off the icon reffence is a private variable on most controls so accessing the reference cannot be done by either extending the control or from the outside of the control. Grrrrrrr this is one of my pet peves sometimes with controls as if this were a protected variable we could extend the control and do what we wanted with it. Bring on Flex 3 and the public input to the code.
Remember I mentioned embedding images in the style sheet to set the icons for button. Well this does the same thing. It creates a new class of type "BitmapAsset" and when the component asks getStyle('buttonOver');
the function actually returns a class reference to "ButtonTest_someImage" or whatever the compiler turned your image into.
So how do I set the icon on a button and allow drawing to it as a function on the button? The answer is what we refer to as a hack. I warn you my answer may not be the best or that pretty but it does work. I will split it into a new post and link to it in 20mins.
UPDATE: HERE IS THE LINK




Ben Stuckie has posted an even better answer to this problem here:
http://blog.benstucki.net/?p=42
Hello everybody, my name is Damion, and I’m glad to join your conmunity,
and wish to assit as far as possible.