Waiting for Flex Effects to Finish - apache-flex

I'm a Flex rookie tasked with enhancing an existing application. One of those enhancements is getting the field that currently shows the time to smoothly fade back and forth between showing the time and the date.
I know the proper way to do this is to embed the font file in the application so I can fade the label in and out directly. I'm trying to avoid that if I can, since I'd prefer to make my changes as unobtrusive as possible.
I came up with what I felt was a reasonable workaround: create a "privacy screen" that just so happens to be the exact size, shape, and color of the clock's background; initialize its alpha to 0; then when changing the time/date, fade-in the privacy screen, make the change, and fade the screen back out again.
The code looks something like this:
var targets:Array = new Array();
targets.push(this.privacyScreen);
this.effectFadeIn.play(targets);
this.mylabel.text = "I am a date and/or time";
this.effectFadeOut.play(targets);
... with the key components looking like this:
<mx:Label text="" id="mylabel" width="100%" height="100%" x="0" y="0" color="0xff0000"/>
<mx:Canvas id="privacyScreen" width="100%" height="100%" x="0" y="0" alpha="1" backgroundColor="{myConfiguration.backgroundColor}"/>
<mx:Fade id="effectFadeIn" alphaFrom="0.0" alphaTo="1.0" duration="250"/>
<mx:Fade id="effectFadeOut" alphaFrom="1.0" alphaTo="0.0" duration="250"/>
As I'm sure the experienced Flex designers already know, this code is made from delicious fresh-squeezed FAIL. The basic assumption that execution will wait for the fade-in effect to finish is wrong, and the fade-out effect is apparently ignored while the fade-in is still in progress.
So I guess I have two related questions:
Is it possible to get execution to pause while waiting for an effect to run to completion?
Is this approach even viable, or does it simply reek of Doing It Wrong from top to bottom?
My thanks in advance for any insight anyone can offer.
(And I admit in advance that the more I try to learn this by doing, the more I realize I need to avail myself of some of the online training resources out there.)

I just played a bit with your code, is this what you're looking for?
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
creationComplete="onComplete();">
<mx:Script>
<![CDATA[
private var targets:Array = new Array();
private function onComplete():void {
targets.push(canv);
effectFadeOut.play(targets);
}
private function onFadeInEnd():void {
effectFadeOut.play(targets);
}
private function onFadeOutEnd():void {
effectFadeIn.play(targets);
}
]]>
</mx:Script>
<mx:Label text="{(new Date()).toString()}" id="lbl" x="0" y="0" color="0xff0000"/>
<mx:Canvas id="canv" width="100%" height="{lbl.height+5}" x="0" y="0" backgroundColor="#000000"/>
<mx:Fade id="effectFadeIn" alphaFrom="0.0" alphaTo="1.0" duration="250"
effectEnd="onFadeInEnd();" />
<mx:Fade id="effectFadeOut" alphaFrom="1.0" alphaTo="0.0" duration="250"
effectEnd="onFadeOutEnd();" />
</mx:WindowedApplication>
Hope that helps :)

Your code is executed while the label fades. this.effectFadeIn.play () does not wait for it to finish. I would add a setTimeout call to the lines of code you need to call later, or better yet, put them in another function. Then, call the function again after a certain interval.
import flash.utils.*;
private function FadeIn () : void {
var targets:Array = new Array();
targets.push(this.privacyScreen);
this.effectFadeIn.play(targets);
this.mylabel.text = "I am a date and/or time";
setTimeout (function (): void {FadeOut (targets);}, effectFadeIn.duration); // Function and duration
}
private function FadeOut (targets : Array) : void {
this.effectFadeOut.play(targets);
setTimeout (FadeIn (), this.effectFadeOut.duration;
}
I'm pretty sure this should work...

Related

More than one titleWindow in a Flex Application

I'm a GIS Analyst that was moved to an Analyst Programmer position. This has been a hard transition for me as I don't have much of a programming background, but I was thrown into it.
I'm working on a Flex app inside a jsp page. Essentially it is a grid 3x2 that has images and text. What I am trying to do is have more than one titleWindow reference in this page, so that when an image is clicked a titleWindow is opened. (If anyone has a better idea, especially if it has to do with a hover I am very open to that!) Currently I have it working for one image. However, when I try to add a second function it errors on me. "Error 1021: Duplicate function definition" Below is the entire code for the main page that calls up the titleWindow. The code below is what gives the Error 1021.
<?xml version="1.0" encoding="utf-8"?>
<![CDATA[
import flash.geom.Point;
import mx.containers.TitleWindow;
import mx.core.IFlexDisplayObject;
import mx.managers.PopUpManager;
import windows.SimplePopupWindow;
private var point1:Point = new Point();
private function showWindow():void {
var login:SimpleTitleWindowExample=SimpleTitleWindowExample(PopUpManager.createPopUp( this, SimpleTitleWindowExample , true));
point1.x=131;
point1.y=119;
point1=roadStatus.localToGlobal(point1);
}
private var point2:Point = new Point();
private function showWindow():void {
var login:SimpleTitleWindowExampleFlood=SimpleTitleWindowExampleFlood(PopUpManager.createPopUp( this, SimpleTitleWindowExampleFlood , true));
point2.x=289;
point2.y=119;
point2=floodplain.localToGlobal(point2);
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:BorderContainer x="10" y="0" width="750" height="600" backgroundColor="#BBB082" backgroundAlpha="1.0" cornerRadius="20" borderColor="#E8DBA7">
<s:Panel x="10" y="10" width="728" height="578" cornerRadius="20" chromeColor="#983D3A" borderColor="#F1EFE7" backgroundColor="#BBB082">
<mx:Image x="131" y="119" width="150" height="115" source="file://GIS Map Portal/images/Map Images/SJCRoadStatus2_small.jpg" id="roadStatus" click="showWindow();"/>
<mx:Image x="289" y="119" width="150" height="115" source="file://GIS Map Portal/images/Map Images/SJCRoadStatus_small.jpg" id="floodplain" click="showWindow();"/>
<mx:Image x="447" y="119" width="150" height="115" source="file://GIS Map Portal/images/Map Images/SJCRoadStatus2_small.jpg"/>
<s:Label x="131" y="242" text="SJC Road Status"/>
<s:Label x="289" y="242" text="SJC Floodplain"/>
<s:Label x="447" y="242" text="Assessor's Parcels"/>
<mx:Image x="131" y="262" width="150" height="115" source="file://GIS Map Portal/images/Map Images/SJCRoadStatus_small.jpg"/>
<mx:Image x="289" y="262" width="149" height="115" source="file://GIS Map Portal/images/Map Images/SJCRoadStatus2_small.jpg"/>
<mx:Image x="446" y="262" width="151" height="115" source="file://GIS Map Portal/images/Map Images/SJCRoadStatus_small.jpg"/>
<s:Label x="131" y="385" text="Label"/>
<s:Label x="289" y="385" text="Label"/>
<s:Label x="446" y="385" text="Label"/>
<s:Label x="229" y="24" text="San Juan County Web Maps" fontFamily="Calvin and Hobbes" fontSize="25"/>
</s:Panel>
</s:BorderContainer>
Below is the titleWindow code. This code works so far!
<?xml version="1.0" encoding="utf-8"?>
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
import mx.controls.Text;
// A reference to the TextInput control in which to put the result.
public var loginName:Text;
// Event handler for the OK button.
private function returnName():void {
//loginName.text="Name entered: " + userName.text;
PopUpManager.removePopUp(this);
}
]]>
</mx:Script>
<mx:HBox width="323" height="147" borderColor="#E8DBA7" dropShadowVisible="true">
<mx:Text text="The San Juan County GIS Department maintains aninteractive web map dedicated for researching county roads, but also includes city limits, lakes and rivers, and other geographic data.
" width="319" height="76" textAlign="center" color="#FFFFFF"/>
</mx:HBox>
<mx:HBox>
<mx:Button label="Go" click="navigateToURL(new URLRequest(''), 'quote')"/>
<mx:Button label="Back" click="PopUpManager.removePopUp(this);"/>
</mx:HBox>
Question: What code do I need to change above to be able to add more than one titleWindow (up to 6), or what code can I use for a hover to open a "window" or tool tip?
If anyone has any ideas or can direct me at all that would be great. I appreciate it!
Sounds like you just got thrown in the deep end. Generally speaking theres no limitation on the number of title windows you can have open, the PopUpManager class handles any UIComponent you tell it to open as a pop up and one of the arguments for the .createPopUp or addPopUp static methods on the manager will take a modal parameter which specifies if the user interaction should be blocked (indicated by blurring the application) or if the window should just be shown. It seems rather this error is stemming from your extension of the TitleWindow (the SimpleTitleWindowExample) can you post that code. Also as starting points on the topic check out the following documentation:
General Flex:
http://www.adobe.com/devnet/flex/videotraining.html
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/index.html
^ notice the runtimes and products selection options at the top of the screen, select according to SDK you're building with (or select SDK based on features)
PopUpManager:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/managers/PopUpManager.html#createPopUp()
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/managers/PopUpManager.html#addPopUp()
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/managers/PopUpManager.html#removePopUp()
Tooltips:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/managers/ToolTipManager.html#createToolTip()
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/managers/ToolTipManager.html#destroyToolTip()
If you're still having troubles definitely post the code for the custom TitleWindow, also what version of the SDK you're using so I can try to replicate.
EDIT:
Ah okay seeing the rest of your code clears it up... you can't have two functions that have the same exact name so in your code you have showWindow as a function that is declared two times (I'm not sure how this is getting past compilation, I would have imagined the compiler would be smart enough to see this error before run-time, but it is what it is). Change the other showWindow to be something like showOtherWindow or something along those lines. It also looks like you come from a procedural programming background (C or some other non-OOP language) Object Oriented programming takes a little while to get your head around but makes a whole lot more sense when it comes to solving real world problems once you understand it, basically you're setting up descriptions and sending messages between objects using method calls and when you define a class, via AS or MXML you're defining the methods (order of method/property definitions doesn't functionally matter, things are still procedural, like step by step within the methods but the order of method declaration or property declaration has no effect).
This may be helpful:
http://www.codeproject.com/KB/architecture/OOP_Concepts_and_manymore.aspx
I'm basically at the opposite end of the spectrum in terms of skills, I have a formal education from DePaul University in computer science but at my current position am doing a lot of google maps flash code so I'm finding myself more and more needing to understand Datums and other GIS specialty info (just thought it was sort of interesting to find someone at the same intersection but going the other way :).

Fxcomponent: Flex video player issue

I'm using the fxcomponent: Flv video player to play my flv/mob files.
You may get it from here.
Now, player works perfectly as shown in their site, but when I try to use the FXVideo control in popup window (popup manager help is here), the component gives mirror image!, strange, I didn't change any code in that.
So can any one help me out to fix this issue, as I'm novice to action script?
Image:
For quick set up, I'm putting my code here:
FXVideo_Example.mxml file (No change at all except variable)
[Bindable]
private var source:String = "http://localhost/greatcatches.flv";
]]>
</mx:Script>
<controls:FXVideo width="480" height="360" source="{source}" autoPlay="false" bufferTime="10" />
MainPage.mxml:
import mx.core.IFlexDisplayObject;
import mx.managers.PopUpManager;
private function showW():void {
// Create a non-modal TitleWindow container.
var helpWindow:IFlexDisplayObject =
PopUpManager.createPopUp(this, FXVideo_Example, false);
}
]]>
</mx:Script>
<mx:VBox width="480" height="360">
<mx:Button click="showW();" label="Show"/>
</mx:VBox>
Ended up by using spark component!
<s:VideoPlayer id="videoPlayer"
source="http://localhost/greatcatches.flv"
autoRewind="true"
muted="true"
horizontalCenter="0"
verticalCenter="0" />

Why does updateDisplayList stop happening in 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).

How we implement "Please wait ...." screen in flex when app is busy

I have a function that restores all of the default settings of my application. This process can take a bit of time, so I would like to implement a "Please wait..." modal popup to let the user know that everything is alright and the program hasn't frozen. Once the function completes its task, I'd like for it to remove the message, and resume normal behavior.
alt text http://www.freeimagehosting.net/uploads/c5906da30c.jpg
On start:
var waitingpopup:TitleWindow = new TitleWindow()
waitingpopup.title = "Please Wait ..."
PopupManager.addPopup(waitingpopup, this, true)
On complete:
PopupManager.removePopup(waitingpopup)
As long as you don't need to convey anything to the user other than "the app is still running", I think a more elegant method would be to just change the cursor:
mx.managers.CursorManager.setBusyCursor()
//do stuff
mx.managers.CursorManager.removeBusyCursor()
The cursor will change to a clock with spinning hands. I'm not sure if there's a way to override this with your own animation, but it's simple and doesn't require you to design your own window.
You can use the PopUpManager to create a Modal PopUp with an animated spinner. The Alert component does this. You can always reference the Alert source code to see how it works.
For those arriving late to this question, Adobe released a Throbber in 4.5:
http://www.adobe.com/cfusion/exchange/index.cfm?event=extensionDetail&loc=en_us&extid=1283019
http://fusiongrokker.com/post/using-the-flex-4-5-busyindicator
http://flexdevtips.blogspot.com/2011/05/simple-animating-preloader-and.html
For example, run the following from the fusiongrokker link above:
private function busyOn():void
{
throbberId.visible = true;
}
private function busyOff():void
{
throbberId.visible = false;
}
]]>
</fx:Script>
<s:VGroup width="100%"
paddingLeft="10"
paddingRight="10"
paddingTop="10"
paddingBottom="10">
<s:BusyIndicator
id="throbberId"
visible="false"
rotationInterval="{rotationInterval}" />
<s:Button
id="start"
click="busyOn()"
width="100%"
height="50"
label="start" />
<s:Button
id="stop"
click="busyOff()"
width="100%"
height="50"
label="stop" />
</s:VGroup>

Programmatically extracting a frame from a video in Flash

I need to write a small Flash app that will need to extract a video frame from a playing video. It will not need to be saved to the HDD of the user. I just need to get the image data and display it in the Flash movie. The frame to extract will be chosen by the user, which is why I'd like to do this purely on the client side (though I know I could do it from the server side).
I've tried searching for solutions but I'm not getting any useful results. Being a Flash newbie I haven't got any code yet seeing as I wouldn't know where to start.
So Flash gurus, is there a way to do this?
If you take a 'screen grab' of a DisplayObject in flash using BitmapData's draw() method.
If you have something for displaying flv somewhere a bit to the right, or down, try something like:
var cloneData:BitmapData = new BitmapData(video.width,video.height,false,0x000000);
cloneData.draw(video);
//test
addChild(new Bitmap(cloneData));
Goodluck!
After reading Georges answer, this is what I came up with as proof of concept. Posting here so it doesn't pollute original question.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="video.load()">
<mx:VideoDisplay id="video" x="0" y="0" source="/content/content.flv" />
<mx:Button x="10" y="10" label="Grab" click="grabClick()"/>
<mx:Button x="71" y="10" label="Play" click="video.play()"/>
<mx:Button x="130" y="10" label="Pause" click="video.pause()"/>
<mx:Script>
<![CDATA[
import mx.controls.*;
import flash.display.BitmapData;
private function grabClick():void {
var bitdata:BitmapData = new BitmapData(video.width, video.height, false, 0x0);
bitdata.draw(video);
var grabResult:Image = new Image();
grabResult.x = 0;
grabResult.y = video.height;
grabResult.source = new Bitmap(bitdata);
addChild(grabResult);
}
]]>
</mx:Script>
</mx:Application>

Resources