create own frames animation and play in movieclip - apache-flex

how can i create own frames animation and play in movieclip or any movieclip extends.. i have this code but is wrong - i'm flash builder beginner so i don't know how work it..i can do it in MovieClip
<?xml version="1.0" encoding="utf-8"?>
public var mc:MovieClip;
protected function application1_creationCompleteHandler(event:FlexEvent):void
{
var comp:UIComponent = new UIComponent();
this.addElement(comp);
mc = new MovieClip();
for (var i:int =0; i<100; i++)
{
var rect:Sprite = new Sprite();
rect.graphics.beginFill(0x330000);
rect.graphics.drawCircle(0, 0, 20);
rect.graphics.endFill();
rect.x=30 + (i%40)*5;
rect.y=100;
mc.addChild(rect);
}
comp.addChild(mc);
}
protected function button1_clickHandler(event:MouseEvent):void
{
mc.play();
}
]]>
</fx:Script>
<s:Button click="button1_clickHandler(event)"/>
thanks for help

Sadly there is no way to create MovieClip animations at runtime, they can only be created using Flash Authoring (or possibly other tools that can export to swf).
Your options are to either create a bunch of Sprite or possibly Shape and add/remove these from the display list as you progress throught the frames. Another option, if your graphics are simpler, you can generate them on the fly for each frame.

I think we'd need a bit more information about the type of animation you're hoping to create.
Depending on what it is, it could be very possible in theory. You'd be creating a separate class that extends MovieClip and instantiate that in your 'for loop'. That class could have all sorts of animation instructions and logic. Extending 'MovieClip' isn't the only option, but it does enable you to use Event.ENTER_FRAME where with a Sprite you'd need to set up an internal Timer or use a public 'update' or 'draw' method that can be called from your main code.
There are also 'Motion' classes that allow you to load XML animation instructions that you have a fair amount of control with. Look up fl.motion.Animator.
What are you trying to do? Welcome to ActionScript!

Related

FLex : unload swf file in SWFLoader

In Flex 3 I have a SWFLoader:
<mx:SWFLoader id="player" source="http://youtube.com/v/..." />
and after some time I invoke player.unloadAndStop(). And I always get this error:
ReferenceError: Error #1056: Cannot create property __tweenLite_mc on _swftest_mx_managers_SystemManager.
What does it mean and how to avoid this?
UPD: AIR 2 doesn't have this problem
Maybe try the Loader class? I'm not sure if it will help but I do all my loading via ActionScript. Generally speaking, I do "heavyWeight" programming/logic/cotrol stuff in ActionScript and leave Flex for more simplistic layout code. That is, flex puts things in place and actionscript controls it all. When loading clips in our Flex 3 project, I have control code along the lines of:
import flash.display.Loader;
private var loader:Loader;
public function init() {
loader = new Loader();
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, loadFailed);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadCompleted);
}
with calls to things like:
//here, pop returns a string like "/path/to/movie.swf"
loader.load(new URLRequest(clipsToPlay.pop()));
...
loader.unload();
contained in functions like:
private function loadNextClip():void {
if(clipsToPlay.length == 0) {
dispatchEvent(new PlayBackCompleteEvent(PlaybackCompleteEvent.ALL));
return;
}
loader.load(new URLRequest(clipsToPlay.pop()));
}
private function loadCompleted(event:Event):void {
currentClip = event.target.content as MovieClip;
loader.unload();
displayClip();
}
private function displayClip():void {
applyEffects();
currentClip.addEventListener(Event.ENTER_FRAME, monitorForCompletion);
addChild(currentClip);
}
I'm not sure if Loader can be used instead of SWFLoader but if so I hope that helps you or someone else, in some way...
EDIT:
I just looked it up and mx.controls.SWFLoader and flash.display.Loader have very similar functionality. I'd try using Loader, as prescribed above, and see if it fixes the problem. You could probably initialize the loader via MXML, too, but I wouldn't recommend it since it's not a visual component, I think it's better to let MXML handle visual things while ActionScript handles logical things.

Is it possible to prevent a flex application from being resized at runtime?

From what I can gather, the resize property of a Flex application is set in the XML config file:
<!--Whether the user can resize the window. Optional. Default true.-->
<!--<resizable></resizable>-->
However, if I set this attribute to true, is there a way to turn this off dynamically at runtime? For example, my application has two view modes - mini and maxi. I would like to prevent the end user from being able to resize the application when in mini mode. I tried prevent the resize using the following code but it does not seem to work:
private function creationComplete():void {
this.systemManager.stage.addEventListener(Event.RESIZE, resizeListener);
}
private function resizeListener(evt:Event):void {
evt.preventDefault();
}
Any help would be greatly appreciated.
There is another way to do that without setting the descriptor file property.
Here is the code:
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" showGripper="false"
layout="vertical" showStatusBar="false"
applicationComplete="init()">
<mx:Script>
<![CDATA[
import mx.events.FlexNativeWindowBoundsEvent;
private function init():void
{
this.stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
nativeWindow.addEventListener(NativeWindowBoundsEvent.RESIZING, onAppResize);
}
private function onAppResize(e:NativeWindowBoundsEvent):void
{
e.preventDefault();
}
]]>
</mx:Script>
Hope this helps.
You'd need to create a new NativeWindow instance and reparent your application into that. When you create a new NativeWindow, you've got options you can set at Initialisation time, including resizable.
http://help.adobe.com/en_US/FlashPlatform//reference/actionscript/3/flash/display/NativeWindowInitOptions.html
According to manual, resizable is read-only property.
So it's probably not possible.
As this was already necro'd, and I was curious:
I was able to implement a switch from resizable to not with the following code:
private var maxMode:Boolean = true;
protected function switchMode():void
{
if (maxMode){
//I chose to freeze the app at current size
//You could also set the min/max to hard coded values
this.maxWidth = this.width;
this.minWidth = this.width;
this.maxHeight = this.height;
this.minHeight = this.height;
}
else {
//default values for WindowedApplication
this.maxWidth = 2880;
this.minWidth = 0;
this.maxHeight = 2880;
this.minHeight = 0;
}
maxMode= !maxMode
}
The user is however still shown the resize mouse icons on the edges of the app.
Try to add return:
evt.preventDefault();
return;

Sharing variables between mxml components

I have several mxml components in an app, all of which need the same variable called genericX. I've included that variable in the main mxml and made it public
[Bindable] public var genericX:Number = 102;
but I still can't access it from other mxml components. If I try to do this for example, it doesn't recognize the variable.
<s:Button x="{genericX}" label="Click" />
There's also a filthy solution that works but isn't nice. You can create a static variable against the application class. For example:
[Bindable] public static var genericX : Object
You can access that from anywhere like this:
MyApplicationName.genericX
It ain't pretty, but it does work :)
simon
You cannot access in this way. There is something called Events in Flex and you need to pass this variable in a MXML file to another using eventDispatcher.
For example
[Bindable] public var genericX:Number = 102;
private function init():void {
var evt:NewCustomEvent = new CustomEvent(CustomEvent.SENDDATA);
evt.genericaValue = genericX
dispatchEvent(evt);
}
Now you need to get into the MXML component where you want to recieve this Event and using addEventListner() to recieve this event and the corresponding variable.
Then finally Inject it into your button.
You should be able to access any global variables with:
Flex 3:
var app:Application = mx.core.Application.application as Application;
Flex 4(looks like what you're using):
var app:Object = FlexGlobals.topLevelApplication;
And then:
<s:Button x="{app.genericX}" label="Click" />
x="{parentApplication.genericX}"
Here is an example for sharing variables between MXML components by declaring them public in the main application.

Flex: Get self SWF file name?

Is there a way I can programmatically determine the filename of the .swf my class is running in?
Thanks!
Stage has a loaderInfo property, which contains a url property that has the information you're looking for. You can get the stage property from any DisplayObject in Flex.
trace(stage.loaderInfo.url);
Just a helpful note: If you load one SWF into another, the loaded (inner) SWF will return an erroneous result if you use loaderInfo.url to try to get the filename. For instance, something like:
Path/To/Outer.swf/[[DYNAMIC]]/1
Instead of:
Path/To/Inner.swf
Beware!
That said, here is the code I use to get the current SWF name:
function SWFName(symbol:DisplayObject):String
{
var swfName:String;
swfName = symbol.loaderInfo.url;
swfName = swfName.slice(swfName.lastIndexOf("/") + 1); // Extract the filename from the url
swfName = swfName.slice(0, -4); // Remove the ".swf" file extension
swfName = new URLVariables("path=" + swfName).path; // this is a hack to decode URL-encoded values
return swfName;
}
Not from within flash, afaik. What do you need it for? There might be a better way to do it.
You can use loaderInfo.loaderURL to get the full path and name of you swf
Example of a class:
public class Main extends Sprite {
private function init():void {
removeEventListener(Event.COMPLETE, init);
var myUrl:String=loaderInfo.loaderURL;
var tmp:Array=myUrl.split("/");
var myName:String=tmp[tmp.length-1].split(".swf")[0];
}
public function Main() {
super();
if (stage)
init();
else
addEventListener(Event.COMPLETE, init, false, 0, true);
}
}
Things have changed a bit in more recent versions so I'll give an answer for Adobe Flash Builder 4.6 (geared towards Flash in browser, but you get the idea).
<s:Application ... applicationComplete="alertSwfUrl()">
<fx:Script>
<![CDATA[
import mx.core.FlexGlobals;
private function alertSwfUrl():void {
var a:LoaderInfo = FlexGlobals.topLevelApplication.stage.loaderInfo;
ExternalInterface.call('alert', a.url);
}
]]>
</fx:Script>
</s:Application
Check out the LoaderInfo docs to figure out how to use the loaderInfo object associated with the stage.

Flex - Sending a parameter to a custom ItemRenderer?

What I am trying to accomplish to to get financial data in my Flex Datagrid to be color-coded--green if it's positive; red if it's negative. This would be fairly straightforward if the column I want colored was part of the dataProvider. Instead, I am calculating it based on two other columns that are part of the dataProvider. That would still be fairly straightforward because I could just calculate it again in the ItemRenderer, but another part of the calculation is based on the value of a textBox. So, what I think I need to be able to do is send the value of the textBox to the custom ItemRenderer, but since that value is stored in the main MXML Application, I don't know how to access it. Sending it as a parameter seems like the best way, but perhaps there's another.
Here is the current code for my ItemRenderer:
package {
import mx.controls.Label;
import mx.controls.listClasses.*;
public class PriceLabel extends Label {
private const POSITIVE_COLOR:uint = 0x458B00 // Green
private const NEGATIVE_COLOR:uint = 0xFF0000; // Red
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
super.updateDisplayList(unscaledWidth, unscaledHeight);
/* Set the font color based on the item price. */
setStyle("color", (data.AvailableFunding >= 0) ? NEGATIVE_COLOR : POSITIVE_COLOR);
}
}
(data.AvailableFunding doesn't exist)
So does anyone know how I would go about accomplishing this?
You may want to look into ClassFactory from the Flex APIs:
This allows you to set a prototype Object with arbitrary types / values each of which will be passed to the item renderer. From the sample:
var productRenderer:ClassFactory = new ClassFactory(ProductRenderer);
productRenderer.properties = { showProductImage: true };
myList.itemRenderer = productRenderer;
The above code assumed that "ProductRenderer" has a public property called "showProductImage" which will be set with a value of "true."
Ah, so I knew about outerDocument but not parentDocument. I was able to just use parentDocument.*whatever I want from the main App and I can access it as long as it's public.
Example:
setStyle("color", (parentDocument.availableFunding >= 0) ? POSITIVE_COLOR : NEGATIVE_COLOR);
Sweet! :)
You can access the value of the TextBox directly, if you need to, by using the static Application.application object, which is accessible from anywhere in your application.
For example, if you wanted the renderers to be notified when the value of the TextInput control changes, you could do something like this (from within your ItemRenderer, and where myTextInput is the ID of the control defined in your main MXML class):
<mx:Script>
<![CDATA[
import mx.core.Application;
private function creationCompleteHandler(event:Event):void
{
Application.application.myTextInput.addEventListener(TextEvent.TEXT_INPUT, handleTextInput, false, 0, true);
}
private function handleTextInput(event:TextEvent):void
{
if (event.currentTarget.text == "some special value")
{
// Take some action...
}
}
]]>
</mx:Script>
With this approach, each item-renderer object will be notified when the TextInput's text property changes, and you can take appropriate action based on the value of the control at that time. Notice as well that I've set the useWeakReference argument to true in this case, to make sure the listener assignments don't interfere unintentionally with garbage collection. Hope it helps!
There's another technique, which, while it initially feels a little hacky is perhaps less cumbersome and cleaner in actual use.
It involves the little-observed fact that an event dispatch is, of course, synchronous and the event object can be treated as a value object populated by any event handler.
i.e. the ItemRenderer can do something like:
...
var questionEvt:DynamicEvent = new DynamicEvent('answerMeThis', true, true);
if (dispatchEvent(questionEvt))
{
if (questionEvent.answer == "some value")
....
With a corresponding handler somewhere up the view hierarchy above the renderer that has a listener on the event and does something like:
function handleAnswerMeThis(event:DynamicEvent):void
{
event.answer = "another value";
event.dataHelper = new DataHelperThingy();
}
etc.
It need not be a DynamicEvent - I'm just using that for lazy illustrative purposes.
I vote up for cliff.meyers' answer.
Here's another example on setting the properties of an itemRenderer from MXML by building a function that wraps a ClassFactory around the itemRenderer class and that injects the necessary properties.
The static function:
public static function createRendererWithProperties(renderer:Class,
properties:Object ):IFactory {
var factory:ClassFactory = new ClassFactory(renderer);
factory.properties = properties;
return factory;
}
A simple example that adds a Tooltip to each item in a list:
<mx:List dataProvider="{['Foo', 'Bar']}" itemRenderer="{createRendererWithProperties(Label, {toolTip: 'Hello'})}"/>
Reference:
http://cookbooks.adobe.com/post_Setting_the_properties_of_an_itemRenderer_from_MXM-5762.html
You use outerDocument property. Please see the fx:Component reference.
You could create an 'AvailableFunding' static variable in the ItemRenderer and then set it in the parent document.
public class PriceLabel extends Label {
public static var availableFunding:int;
...
...
SetStyle("color", (PriceLabel.availableFunding >= 0) ? NEGATIVE_COLOR : POSITIVE_COLOR);
}
In your parent document, set it when your text box gets updated
PriceLabel.availableFunding = textBox.text;
Obviously it'll be the same value for every ItemRenderer but it looks like that might be what you're doing anyway.
I like to override the set data function of the item renderer to change the renderer when the data provider changes as shown here
When you override the function you could cast the object to your object to make the availableFunding property available.
To access the text box you could try creating a public property and binding the property to the text box in the mxml file:
public var textVar:String;
<mx:itemRenderer>
<mx:Component>
<customrenderer textVar="{txtBox.text}" />
</mx:Component>
</mx:itemRenderer>
Nice ClassFactory Example here
See this example:
itemRenderer="{UIUtils.createRenderer(TextBox,{iconSrc:IconRepository.linechart,headerColor:0xB7D034,subHeaderColor:0xE3007F,textColor:0x75757D})}"

Resources