How to get the reference to a newly created Button with Actionscript? - apache-flex

I have a MXML button:
<mx:Button id="myButton1"/>
How do I create N number of Buttons with Actionscript: myButton2, myButton3, myButton4... myButtonN ?
And how to get the reference to the newly created buttons right after they are created? Like
I should be able to do myButtonN.x = 100 right after it's created.

This is pretty basic stuff...you might want to start with some Flex tutorials, or read through one of the many excellent books.
Here's a blob of code for you to copy & paste and see how it works for you:
private var buttons:Array = [];
public function createButtons():void {
for(var i:int=0; i<100; i++) {
buttons[i] = new Button();
buttons[i].label = "Button "+i;
buttons[i].x = i * 50;
addChild(buttons[i]); // NOTE: use addElement instead of addChild in Flex 4
}
}
It's not tested, so might need some minor typos, but you should be able to get the idea.

Related

How to use a symbol from an external swf as image in TextArea?

I hope someone will be able to help here, so first of all though let's take a look at exactly what my problem is ...
I would have liked to insert a movieclip from an external swf into my textarea but I think it isn't as easy as I thought... because the Textarea,TextFlow components are unfortunately almost unusable to me in this respect ..
I have read the API of Textarea and TextFlow , and I searched a lot on Google and some forums, but I have not found the solution to my problem.
I have found similar topics to this one like as :
Using symbol from library in htmlText <img> tag in ActionScript 3
http://help.adobe.com/en_US/AS2LCR/Flash_10.0/help.html?content=00000322.html
I have tried several ways to refer to the symbol but to no avail...
Here is my code :
[Bindable]
/**
* The text which will be displayed
**/
public var pblMessages:String = "";
<s:TextArea id="pblArea" left="10" right="242" top="241" bottom="55" editable="false"
textFlow="{TextConverter.importToFlow(pblMessages,TextConverter.TEXT_FIELD_HTML_FORMAT)}"
valueCommit="pblAreaCommitHandler(event)">
</s:TextArea>
Method for adding new line :
private function submitText(keyPress:Boolean=false) :void {
if (pblInput.text=="") {
pblInput.setFocus();
return;
}
var format:ElementFormat = new ElementFormat();
var fontDescription:FontDescription = new FontDescription("Arial");
format.fontSize = 11;
format.fontDescription = fontDescription;
var s:String = pblInput.text;
var re: RegExp = new RegExp("\r|\n","gi");
s = s.replace(re,"");
var inlineGraphicElement:InlineGraphicElement = new InlineGraphicElement();
inlineGraphicElement.source = Smileys.smi_kiss;
var p:ParagraphElement = new ParagraphElement();
p.addChild(inlineGraphicElement);
//pblArea.textFlow.addChild(p);
pblMessages += "<font color='#000000'>" + s + "</font><img src='assets/testmovie.swf#smi_kiss' width='20' height='20'/><br/>";
pblInput.text="";
}
If the smiley is displayed on the first frame in the swf, then it displayed (without symbol) too in the TextArea of course.. but I don't want to make 100 different swf file.. I'm quite sure that the smileys can be displayed by using symbols.
Thank you in advance for your help.
Try to create complete TextFlow without using TextConverter.importToFlow. After adding inlineGraphicElement to p, you should add a SpanElement to p, and then add text to SpanElement.text, and then assign a textFlow to pblArea.textFlow.

Flex 4.6 Need to know how to animate a .swf in actionscript

I've converted a PowerPoint into Flash so each slide is a .swf. I've used a number of different converters and the problem here is the same.
What I'd like to do is trigger the .swf's animation (contents of slide appearing) programatically. I can click on the .swf with a mouse and the animation advances. I can automate this when the .swf's embedded in a web page simply by doing:
document.getElementById('myMovie').play();
Each time I execute that code, the swf advances to the next animation. However, I can't find a way to do this in flex. I've used then MovieClipSWFLoader and tried:
private function animate():void {
var simulatedClick1:MouseEvent = new MouseEvent(MouseEvent.CLICK);
var simulatedClick2:MouseEvent = new MouseEvent(MouseEvent.MOUSE_DOWN);
var simulatedClick3:MouseEvent = new MouseEvent(MouseEvent.MOUSE_UP);
frameNo++;
myMovie.gotoAndStop(frameNo);
myMovie.nextFrame();
myMovie.nextScene();
myMovie.play();
myMovie.dispatchEvent(simulatedClick1); // with clicks 1, 2, and 3
}
<s:MovieClipSWFLoader id="myMovie" source=""/>
<s:Button id="btnAnimate" click="animate()"/>
I've also tried loading as an Image component and using the simulated click too... no good. Can anyone tell me how I can do this?
The problem was that the .swf was created with Flash 8 and wasn't compatible with my version of Flex. I found a great solution in ForcibleLoader at https://gist.github.com/nsdevaraj/409902. It converts old .swf's to new ones and then the code worked as it should.
private var libMC:MovieClip = new MovieClip();
ur = new URLRequest(guide_url);
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, swfComplete);
var fLoader:ForcibleLoader = new ForcibleLoader(loader);
fLoader.load(ur);
swfMovie.addChild(loader);
private function swfComplete(event:Event):void{
libMC = event.currentTarget.content as MovieClip;
}
private function animate():void {
libMC.nextFrame();
<mx:UIComponent id="swfMovie"/>

Is there a way to get a list of all skin classes in the current application?

Is there a way to get a list of all the skin classes that are in the current application? I'm using Flex 4.5.1.
Here is the loop that I'm using now to get all the skins,
for each (var item:Object in styleManager.typeHierarchyCache) {
for (label in item) {
if (label=="spark.components.supportClasses.Skin" ||
label=="spark.skins.mobile.supportClasses.MobileSkin") {
for (label in item) {
name = label.substr(label.lastIndexOf(".")+1);
vo = new SkinObject();
vo.name = name;
vo.qualifiedName = label;
dictionary[label] = vo;
}
break;
}
}
}
for each (item in dictionary) {
array.push(item);
}
The reason why is because I want to list all the skins in the application and then be able to apply them in real time so I can see what they look like. * I have this working but I was hoping for a better way.
You definitely could iterate through all objects on the screen and see if they're of type SparkSkin. Something like this:
private function findSkins():void
{
recurseComponent(FlexGlobals.topLevelApplication);
}
private function recurseComponent(parent:UIComponent):void
{
var child:UIComponent;
for(var i:uint = 0, len:uint = parent.numElements; i<len; i++)
{
child = parent.getElementAt(i) as UIComponent;
if(child && child is SparkSkin)
{
trace("Skin Found!"); // trace whatever you need here
}
recurseComponent(child);
}
}
But be warned that this solution is very expensive since it needs to iterate through all objects on the screen, which can go into several thousands. However, I really don't see what's the purpose of this and would definitely not recommend it other than for debugging/testing purposes.
Edit: Also, this will only work for skins on the display list. Skins mentioned in CSS will not be recognized and I'm fairly sure there's no way of figuring that out short of going through all the css and see if there's a skinClass property. But then it won't catch any default skins or skins set in actionscript or inline mxml.

Add Child immediately in Flex 3

I'm having a problem similar to FLEX: dialog not display immediately . Code follows:
private function saveBitmap(event:ContextMenuEvent):void
{
loadingScreen.visible = true;
loadingScreen.appLoadingText.text = "Preparing bitmap...";
addChild(loadingScreen);
validateNow();
var bmpd:BitmapData = new BitmapData(canv.width, canv.height);
bmpd.draw(canv);
var fr:FileReference = new FileReference();
fr.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, removeLoadingScreen);
fr.addEventListener(Event.CANCEL, removeLoadingScreen);
var png:PNGEncoder = new PNGEncoder();
var iba:ByteArray = png.encode(bmpd);
fr.save(iba, "export.png");
}
Basically, bmpd.draw and/or png.encode are dog slow, so I'd like to have a nice "please hold while we prepare your png" dialog to appear. I can't use callLater() because of the FileReference.
And just for good measure, the loading screen appears at the same time the save dialog appears from the call to fr.save().
Any ideas?
Cheers!
You're adding the child in this function. Are you doing any other work to the loadingScreen, such as sizing it? Or positioning it? Most commonly this is done in updateDisplayList(). What container are you using?
Are you sure the Z-order of your two children is correct? You can swap children with the swapChildren method

How do I implement custom drag functionality in a Flex list control?

Flex has built in drag-n-drop for list controls, and allows you to override this. But they don't cover this in examples. The built-in functionality automatically drags the list-item, if you want to override this you find the handlers are being set up on the list itself.
What I specifically want to do, is my TileList shows small thumbnails of items I can drag onto a large Canvas. As I drag an item from the list, the drag proxy should be a different image.
So, I followed the technique suggested and it only works if I explicitly set the width/height on the proxy Image. Why?
It's not obvious until you've tried it =) I struggled with the same thing just a few weeks ago. This was my solution:
The list:
<List>
<mouseDown>onListMouseDown(event)</mouseDown>
</Tree>
The mouse down handler:
private function onMouseDown( event : MouseEvent ) : void {
var list : List = List(event.currentTarget);
// the data of the clicked row, change the name of the class to your own
var item : MyDataType = MyDataType(list.selectedItem);
var source : DragSource = new DragSource();
// MyAwsomeDragFormat is the key that you will retrieve the data by in the
// component that handles the drop
source.addData(item, "MyAwsomeDragFormat");
// this is the component that will be shown as the drag proxy image
var dragView : UIComponent = new Image();
// set the source of the image to a bigger version here
dragView.source = getABiggerImage(item);
// get hold of the renderer of the clicked row, to use as the drag initiator
var rowRenderer : UIComponent = UIComponent(list.indexToItemRenderer(list.selectedIndex));
DragManager.doDrag(
rowRenderer,
source,
event,
dragView
);
}
That will start the drag when the user clicks an item in the list. Notice that I don't set dragEnabled and the other drag-related properties on the list since I handle all that myself.
It can be useful to add this to the beginning of the event handler:
if ( event.target is ScrollThumb || event.target is Button ) {
return;
}
Just to short circuit if the user clicks somewhere in the scrollbar. It's not very elegant but it does the job.
I found a simpler answer here. That example extends a DataGrid control, but you can do the same with a List control. In my case, I use an image source instead of Class:
public class CustomDragList extends List {
[Bindable]
public var dragProxyImageSource:Object;
override protected function get dragImage():IUIComponent {
var image:Image = new Image();
image.width = 50;
image.height = 50;
image.source = dragProxyImageSource;
image.owner = this;
return image;
}
}
Then use that custom list like this:
<control:CustomDragList
allowMultipleSelection="true"
dragEnabled="true"
dragProxyImageSource="{someImageSource}"
dragStart="onDragStart(event)"/>
Where 'someImageSource' can be anything you'd normally use for an image source (embedded, linked, etc.)

Resources