Calling and removing instances of a timer - actionscript-3

In my code, I utilize two timers:
var timerScroll:Timer = new Timer();
var timerCollission:Timer = new Timer();
First of all... how do I actually call timerScroll/timerCollission to get it's current value...
and for later on...
how do I reset or remove the timer instance from either of them so I can start anew?
I've tried doing like timerScroll.getTimer();... and timerScroll.flash.utils.getTimer();... which I figured wasn't going to work but tried it anyways =D

Use a timer like this:
var timerScroll:Timer = new Timer( 2000 ); //2000ms = 2 second interval
timerScroll.start();
timerScroll.stop();
timerScroll.reset();
Then, in a separate event listener, apply your callback function to the TIMER event.
timerScroll.addEventListener(TimerEvent.TIMER, myCallback);
function myCallback(e:TimerEvent) {
trace( timerScroll.currentCount() );
}
See the API docs here: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/utils/Timer.html

Related

How to keep timer running when i go to the other frame Actionscript 3.0

I am new to actionscript.
I want to know how to run timer class and keep running even when i go to other frame.
For example. I run timer in frame 2 and when i go to frame 1 timer keeps running, until i go back to frame 2 to stop the timer.
I appreciate the help.
UPDATE :
I try to make a stopwatch with these code :
var sec,min,hr:uint = 0;
sec_txt.text = min_txt.text = hr_txt.text = "00";
var timerStopWatch:Timer = new Timer(1000);
timerStopWatch.addEventListener(TimerEvent.TIMER, timerHandler);
function timerHandler(e:TimerEvent){
var sec:String = String(uint(timerStopWatch.currentCount%60));
var min:String = String(uint((timerStopWatch.currentCount/60)%60));
var hr:String = String(uint((timerStopWatch.currentCount/60)/60));
sec_txt.text = (uint(sec)< 10) ? "0" + sec:sec;
min_txt.text = (uint(min)< 10) ? "0" + min:min;
hr_txt.text = (uint(hr) < 10) ? "0" + hr:hr;
}
When i start the timer it work, but when i go to the second frame or another it stop and show a output error :
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at Stopwatch_fla::MainTimeline/timerHandler()
at flash.utils::Timer/_timerDispatch()
at flash.utils::Timer/tick()
What i want is, when i start the Timer and go to the other frame it will still running(ticking) and when i go back to the Timer frame i could stop it.
First, if you're going to be re-visiting the frame where your posted code lives, you want to make sure that timer doesn't get re-created every time and cause a memory leak.
Change the following line
var timerStopWatch:Timer = new Timer(1000);
To these two lines:
var timerStopWatch:Timer;
if(!timerStopWatch) timerStopWatch = new Timer(1000);
This will ensure your timer is only created once. That event listener will keep the timer in memory, so if you're constantly creating new timers and adding a listener to them, they will all stay in memory and your application will get slower and slower.
Second, make sure you clean up after yourself.
When you want your timer to be gone, stop it, remove the event listener and null the reference:
timerStopWatch.stop();
timerStopWatch.removeEventListener(TimerEvent.TIMER, timerHandler);
timerStopWatch = null;
Third, if your going to have this object span multiple frames, anything that is referenced in the event handler needs to persist in those frames as well.
That means:
sec_txt
min_txt
hr_txt
All have to exist on any frame where this timer is running. Make sure on those frames that they have their instance names set properly.
OR, check if they exist prior to using them:
if(sec_txt) sec_txt.text = (uint(sec)< 10) ? "0" + sec:sec;
If you have this problem you are probably typing code in the frame itsel. Write a document class and create your timer in there, so no matter which frame, all properties are still there and keep running.

closures with popups using flex 4.6

I have this custom event handler that shows a popup and accepts input from the user:
private var mySkinnablePopupContainer:MySkinnablePopupContainer;
private function handleShowGridPopupEvent(event:ShowGridPopupEvent):void {
var mouseDownOutSideHandler:Function = function(mdEvent:FlexMouseEvent):void {
// At this point, event.targetControl contains the wrong object (usually the previous targetControl)
if (mdEvent.relatedObject != event.targetControl) {
mySkinnablePopupContainer.close();
}
}
var gridPopupSelectionHandler:Function = function(popEvent:PopUpEvent):void {
if (!popEvent.commit) return;
// At this point, event.targetData contains the wrong object (usually the previous targetData)
myModel.doSomethingWithData(popEvent.data.selectedItem, event.targetData);
}
if (!mySkinnablePopupContainer) {
mySkinnablePopupContainer = new MySkinnablePopupContainer();
mySkinnablePopupContainer.addEventListener(PopUpEvent.CLOSE, gridPopupSelectionHandler);
mySkinnablePopupContainer.addEventListener(FlexMouseEvent.MOUSE_DOWN_OUTSIDE, mouseDownOutSideHandler);
}
// At this point, event.targetData contains the correct object
mySkinnablePopupContainer.dataProvider = getMyDPArrayCollection(event.targetData);
mySkinnablePopupContainer.open(this);
var point:Point = event.targetControl.localToGlobal(new Point());
mySkinnablePopupContainer.x = point.x + event.targetControl.width - mySkinnablePopupContainer.width;
mySkinnablePopupContainer.y = point.y + event.targetControl.height;
}
Every time the function handler gets called, it will have the correct ShowGridPopupEvent object but by the time it calls the
gridPopupSelectionHandler, it will contain the old object from a previous call. It works the first time, subsequent calls fails.
Somehow the reference to the event object changed somewhere in between before opening the popup and after.
Any idea what am I doing wrong here? Is this a bug with flex?
found the prob. since im attaching listener only once, it will reference the old listener, with the reference to the old data. i guess i was expecting its reference to be updated whenever i create the closure. not in this case. possible fix is to remove the listener and re-add it again but I abandoned the idea of using closures, and aside from what RIAStar mentioned, it is also impractical as it only gives more overhead by creating a new function for every invocation of the handler.

as3 addEventListener to .copyTo()

Is there a way to add an event listener to the copyTo() function so I
can run code once the action is complete?
Below is my code and that last line is what I would assume might work, but it doesn't.
var sourceDir:File = File.applicationDirectory.resolvePath("userSettings.xml");
var resultDir:File = File.applicationStorageDirectory.resolvePath("userSettings.xml");
sourceDir.copyTo(resultDir, true);
// Is this possible?
sourceDir.addEventListener(Event.COMPLETE, fileCopied);
According to DOCUMENTATION no, but copyToAsync() function is dispatching Event.COMPLETE.

How to call a function at specified date time?

I want to call a method at 23:55 of the day,
how to do this in actionscript 3?
I'd say you create a loop that checks the current time throught the Date Object.
package {
import flash.display.Sprite;
import flash.utils.clearInterval;
import flash.utils.setInterval;
public class TimeCheck extends Sprite
{
private var interval:int;
public function TimeCheck()
{
interval = setInterval( checkTime, 1000 );//check performed every second
checkTime();
}
private function checkTime():void
{
var date:Date = new Date();
if ( date.hours == 23 && date.minutes == 55 )//actual time check
{
clearInterval( interval );//kills the loop
//... do something ...
}
}
}
}
note that this is executed client-side so the client time will be used. there may be a way to sync it to a server time though.
hope it helps
AS3 has timeouts (e.g. setTimout) like JavaScript. The use of setTimeout in AS is talked about here. Given the two dates (now and when the alarm should trigger), compute the difference in milliseconds and use it as the timeout parameter.
Alternatively (and ever so much less efficiently, but not enough to bat an eye over), setTimeout could be run every minute and if it is the "magical time" (or past it when the previous interval was before!, remember need 2x the frequency to observe all changes and a clock-shift could occur...) then sound the alarm.
Note that there are some limitations like the AS host being closed during the timeout period or clock shifts. Likely no DST to worry about here, but daylight-savings issues do come up when dealing with dates/times.
Happy coding.
Edit: AS also has the Timer class which is an wrapper for setTimeout/setInterval/clearTimeout/clearInterval functionality. In any case, if "working with objects" is preferred.
I haven't tested it but something like this should work...
var eventDate:Date = new Date();
eventDate.setHours( 23, 55 );
var now:Date = new Date();
var delay:Number = eventDate.time - now.time;
if( delay > 0 )//if we haven't yet passed 23:55
{
var timer:Timer = new Timer( delay , 1 );
timer.addEventListener( TimerEvent.TIMER , yourMethod );
timer.start();
}
I believe the above solutions work; however, they appear to be very costly in terms of performance. I have a two-liner that is (relatively) elegant and straight-forward. The solution uses an anonymous function, client-side time, and assumes you are given a parameter, startDate:Date. I have not tested this, so there might be a simple logic error, but the idea should give someone ideas.
var timer:Timer = (new Timer(startDate.time - (new Date()).time, 1)).addEventListener(TimerEvent.TIMER, function():void {
// This area is called after the allocated time.
});
timer.start();

ActionScript 3 name property is not returning the right name...?

I experienced a problem with the name property in as3, I created this "dot" movieclip and I exported to a class,
then I anonymously created a bunch of dots using a loop. I assigned numbers as name to each dots
private function callDots(num:Number):void
{
for (var i = 0; i < subImagesTotal[num]; i++)
{
var d:Dot = new Dot();
d.x = i*23;
d.y = 0;
d.name = i;
dotContainer.addChild(d]);
}
}
so far so good, I checked that if I trace the name here, I will get the number I want.
However, it's not giving me the numbers if I trace it in other functions.
I added all of my dots to "dotContainer", and if I click on one of the dots, it will call this function
private function callFullSub(e:MouseEvent):void
{
var full_loader:Loader = new Loader();
var temp:XMLList = subImages[sub];
var full_url = temp[e.target.name].#IMG;
full_loader.load(new URLRequest(full_url));
full_loader.contentLoaderInfo.addEventListener(Event.INIT, fullLoaded);
}
e.target.name is suppose to be numbers like 1 or 2, but it's giving me "instance66" "instance70" and I
have no idea why. Because I did the same thing with loaders before and it totally worked.
Any ideas? Thanks.
christine
The e.target returns the inner most object clicked on, this could be a TextField, another MovieClip or posibly a shape (I'm not 100% of the last one) inside the "Dot".
To prevent this you could try to set the mouseChildren property to false on the Dot's when you add them. This should insure that nothing inside the dots can dispatch the click event, and thus the Dot's should do it.
Perhaps you could also in the event handler verify the target type with code like this:
private function callFullSub(e:MouseEvent):void
{
if(!e.target is Dot)
throw new Error("target in callFullSub is not Dot but: " + e.target.toString());
//The rest of you code here
}
The answer is [e.currentTarget.name] I perform this all the time!
Should return "Dot1" "Dot2", etc.
If the value you wish to return is a number or other data type other than a string (name of object) use [e.currentTarget.name.substr(3,1).toString()]
Should return 1, 2, etc.
Navee
I tried to reproduce your problem first with Flex using runtime created movieClips and then with Flash using Dot movieClip symbols exported for ActionScript. Neither application exhibited the problem.
You may already know names like "instance66" "instance70" are default enumerated instance names. So, whatever is dispatching the MouseEvent is NOT the dot instance. Perhaps you are unintentionally assigning callFullSub to the wrong targets, maybe your containers? Try assigning it to dot instance right after you create them, like this:
private function callDots(num:Number):void
{
for (var i = 0; i < subImagesTotal[num]; i++)
{
var d:Dot = new Dot();
d.x = i*23;
d.y = 0;
d.name = i;
d.addEventListener(MouseEvent.CLICK, callFullSub);
dotContainer.addChild(d]);
}
}
Be sure to temporarily comment out your original assignment.
Try this might work,..
d.name = i.toString();
You have not shown enough of your code for me to be able to give you a DEFINATE answer, I will however say this.
//After you create each loader you need to set its mouseEnabled
//property to false if you do not want it to be the target of
//Mouse Events, which may be superseding the actual intended target;
var full_loader:Loader = new Loader();
full_loader.mouseEnabled = false;
//Also you could name the loaders and see if what comes back when you click is the same.
ALSO! Add this to your Mouse Event handler for CLICK or MOUSE_DOWN:
trace(e.target is Loader); //If traces true you have an answer
I believe that the mouse events are being dispatched by the Loaders.
please provide more of your code, the code where the Loader.contentLoaderInfo's COMPLETE handler fires. I assume this is where you adding the loaders to the display list as I cannot see that now.