PDA

View Full Version : eventListener for a changed variable



Yuu
June 26th, 2008, 01:11 PM
So I'm confronted with a problem, that eventListener seems to be lacking to tools to directly over come.

I've got a global variable, from a class that multiple SWFs I've got going share. I want fire off a function in a child, to be exact, the child of a child, SWF when that variable is changed by the parent.

It seems to me an easy way to do this would be to have an eventListener than detects changes in a variable. But there doesn't seem to be any way to directly do that via a listener - at least from what I gather from:
http://edutechwiki.unige.ch/en/ActionScript_3_event_handling_tutorial

I can fudge it with enterFrame in that child- but that seems like a really ham fisted solution to have it constantly checking like that.

I'm still a novice, so be gentile when explaining things.

Anogar
June 26th, 2008, 01:34 PM
Hi there Yuu,

A good way to do this sort of thing is a public set function. What this does is it allows you do dispatch events, check for conditionals, manipulate the input, etc. It looks something like this.



public function set myVariable(input:int):void
{
_myVar = input;
dispatchEvent(new Event("myVarChanged"));
}

You could also do something like this, if you wanted to limit the input that your variable would accept from other classes:



public function set myVariable(input:int):void
{
if (input < 10)
{
_myVar = input;
dispatchEvent(new Event("myVarChanged"));
}
}

If you're not using classes you can still use a set function, just leave out the 'public' keyword. To use this function, you use the name of the function, not the name of the variable. They cannot be named the exact same thing. So, in my example, you would use it like this:



myVariable = 5; //event dispatched - variable changed.

Hope that helps. :thumb:

Yuu
June 26th, 2008, 02:47 PM
Thanks, it's getting me on a track - but I can't finish thing out yet.

Long story short I've got a parent that loads a child (child1.swf) that child loads other swfs (child1_1.swf). I've got parent set up to listen for a Resize, then set a global variable in a class (MyGlobalVars). I need child1_1 to also respond to that resize - I think I'm failing with the eventListener in child1_1. I just don't know how to listen for something coming from the parent, of the parent of the swf that needs to change... :crying:

The global variable works, I've tested using the enterFrame kludge

This is all on the respective timelines..

From parent:


import MyGlobalVars;
stage.addEventListener(Event.RESIZE, resizeHandler);

function resizeHandler(e:Event):void
{
myVariable = stage.stageWidth;
MyGlobalVars.currentStageWidth = stage.stageWidth;
}

function set myVariable(input:int):void
{
//_myVar = input;
dispatchEvent(new Event("myVarChanged"));
trace ("Input from myVaible = " +input);
}



From child1_1


import MyGlobalVars;
addEventListener("myVarChanged", changeVar);

function changeVar (e:Event):void
{
trace ("Content Template Relizes the stage has been Resized" + MyGlobalVars.currentStageWidth)
}



And the MyGlobalVars class


package
{
public class MyGlobalVars
{
public static var currentStageWidth:Number;
}

}

Anogar
June 26th, 2008, 02:50 PM
You're not actually setting the global variable with the set function. Put the set function inside the MyGlobalVars class.

Yuu
June 26th, 2008, 03:05 PM
Thanks for the quick response(s)

Ok, that's what I thought at first, but for some dumb reason I decided to make it difficult.

I've got an issue with the package now:
"1180: Call to a possibly undefined method dispatchEvent."

I'm probably being very dense.., at least feel like it.



package
{
import flash.events.Event;
import flash.events.EventDispatcher;

public class MyGlobalVars
{
public static var currentStageWidth:Number;

public function set myVariable(input:int):void
{
currentStageWidth = input;
dispatchEvent(new Event("myVarChanged"));
trace ("set myVariable triggered from class");
}
}

}

Anogar
June 26th, 2008, 03:43 PM
Try having MyGlobalVars extend EventDispatcher.

Yuu
June 26th, 2008, 04:24 PM
Thanks, that cured that error.

But I'm still not at all sure how to trigger the function in my class from the timeline of the parent, and in turn have it set off a listener in child1_1

If I could figure out how to get the function in the class triggered, I think I can get the child going. But this is my 1st time working with this manner of script, and I'm just not grasping something. The more I try, the worse it seems to be getting.

From parent


stage.addEventListener(Event.RESIZE, resizeHandler);
function resizeHandler(e:Event):void
{
MyGlobalVars.currentStageWidth = stage.stageWidth;
//Something to trigger function myVariable in class MyGlobalVars goes here - I hope.
}



There's got to be some concept that I'm just not catching onto, but I'm getting frustrated to the point I just can't see it.

Anogar
June 26th, 2008, 04:48 PM
You need to be accessing the setter when you set it, not the variable. Like this:



MyGlobalVars.myVariable = stage.stageWidth

Add the listener to the MyGlobalVars class, like this:



MyGlobalVars.addEventListener("myVarChanged", doSomething);

Yuu
June 26th, 2008, 05:08 PM
I've got to be an idiot or something... I'm trying to follow what you're telling me - but all I get is errors. I think I need a punch in the brain or something. Am I just hopeless?

Below is what I've got - I get errors in both the class and timeline codes now

MyGlobalVars Class


package
{
import flash.events.Event;
import flash.events.EventDispatcher;

public class MyGlobalVars extends EventDispatcher
{

public static var currentStageWidth:Number;

public function set myVariable(input:int):void
{
currentStageWidth = input;
dispatchEvent(new Event("myVarChanged"));
trace ("set myVariable triggered from class");
}


MyGlobalVars.addEventListener("myVarChanged", doSomething);

public function doSomething():void {
trace ("Do Something");
}
}

}

From the time line of parent


stage.addEventListener(Event.RESIZE, resizeHandler);

function resizeHandler(e:Event):void
{

MyGlobalVars.myVariable = stage.stageWidth;
}

Anogar
June 26th, 2008, 05:09 PM
Wait, no, add the event listener to wherever you want the interaction to happen, not to the Global class.

Yuu
June 26th, 2008, 05:18 PM
Still got problems - having the following lines of code in the time line's causing errors.

MyGlobalVars.myVariable = stage.stageWidth

gets me:


1119: Access of possibly undefined property myVariable through a reference with static type Class.


And
MyGlobalVars.addEventListener("myVarChanged", doSomething);


1061: Call to a possibly undefined method addEventListener through a reference with static type Class.

Yuu
June 26th, 2008, 05:26 PM
I'm knocking off for the day. Thanks for all the help, though I seem hopeless.

If you're up for it - I'll be back at it tomorrow.

Anogar
June 26th, 2008, 06:30 PM
I'll be here tomorrow. I think your best bet is a singleton data pattern, I'll show you tomorrow what that means.

Yuu
June 27th, 2008, 12:06 PM
Ok, I took some time and made a set of FLAs that are stripped of the other junk I've been working at, so the issue at hand can be focused on. Hopefully this will help ease the pain of trying to sort this out.

You can download all of the files HERE (http://www.batescreativegroup.com/ResizeTest/ResizeTest.zip)

I've also posted the SWFs here (http://www.batescreativegroup.com/ResizeTest/)

In doing so, I realized I've missed a big issue.
stage.addEventListener(Event.RESIZE, doMyFunction);
works just fine in the Flash player when I was testing it... but hah, I doesn't realize things have changed when it's in the HTML... dur. I was so focused on the other problem I missed this issue.

So if anyone an point me to the solution to that.. it'd be appreciated. I'll start on my own research

TheCanadian
June 27th, 2008, 02:12 PM
You could also use the flash.utils.Proxy class.

Yuu
June 27th, 2008, 03:34 PM
You could also use the flash.utils.Proxy class.

I just looked that up, and I think it's over my head at the moment. I'm not sure where to being to apply it correctly. Guess I need to study up.

So I'm still stuck with a child MoviceClip that's not resizing...

But I found a nice simple solution to that issue I was having, once the SWF was in HTML. Har, set the dimensions to 100% in the HTML and off you go. Just goes to show how much frustration can hamper your ability to complete a task. I was messing with to dimension parameters in the HTML, but didn't think %... duh.

Felixz
June 27th, 2008, 04:02 PM
NO,NO,NO,NO,No,No,No,no,no, wrong!
You forget about cucial things:
package {
import flash.events.EventDispatcher;
//import flash.events.VariableEvent;
import flash.events.Event;
public class MyGlobalVars {
private static const _dispatcher:EventDispatcher = new EventDispatcher();
private static var _currentStageWidth:Number;
public static function get currentStageWidth():Number {
return _currentStageWidth;
}
public static function set currentStageWidth(value:Number):void {
_currentStageWidth=value;
_dispatcher.dispatchEvent(new Event("stageWidthChange"));
//I'd recommend a Custom Event:
//_dispatcher.dispatchEvent(new VariableEvent("stageWidthChange",false,false,value));
}
//-----------------------------------------------------------
public function MyGlobalVars() {
throw new IllegalOperationError("MyGlobalVars is static class.");
}
public static function addEventListener(type:String, listener:Function):void {
_dispatcher.addEventListener(type, listener, false, 0, false);
}
public static function removeEventListener(type:String, listener:Function):void {
_dispatcher.removeEventListener(type, listener, false);
}
public static function dispatchEvent(event:Event):Boolean {
return _dispatcher.dispatchEvent(event);
}
public static function hasEventListener(type:String):Boolean {
return _dispatcher.hasEventListener(type);
}
}
}

Yuu
June 27th, 2008, 04:21 PM
NO,NO,NO,NO,No,No,No,no,no, wrong!
You forget about cucial things:

Heh. To say I forgot would imply I knew it in the 1st place. But sadly, I didn't even know how wrong I was.

And I'm still not sure how to trigger currentStageWidth. I've got a listerner on the timeline listening for the resize, which works fine, on the timeline. But I don't understand how to call functions in the class from the timeline properly.

This project is my 1st foray into AS3, and I keep getting asked to do additional things (like the resizing) as it goes. Which is making really though on me.

I learn best by seeing complete examples that I can mess with and break intentionally. So trying to work stuff out in pieces isn't the easiest for me.

Felixz
June 27th, 2008, 04:40 PM
MyGlobalVars.addEventListener("stageWidthChange",traceIt);
function traceIt(event:Event):void {
trace(MyGlobalVars.currentStageWidth);
}
//------------------------
MyGlobalVars.currentStageWidth=34535;
MyGlobalVars.currentStageWidth=.656546;
MyGlobalVars.currentStageWidth=45646456;

Anogar
June 27th, 2008, 05:00 PM
Heh, making the poor guy use composition to get event dispatcher functionality may be the right way to do it, but it's a little much for his first project. Just stick with extending it, inheritance is fine while learning imo.

Either way, I think perhaps your base assumptions about needing that GlobalVars class may be off - are you just trying to keep track of the stage width?

Yuu
June 27th, 2008, 07:44 PM
Heh, making the poor guy use composition to get event dispatcher functionality may be the right way to do it, but it's a little much for his first project. Just stick with extending it, inheritance is fine while learning imo.

Either way, I think perhaps your base assumptions about needing that GlobalVars class may be off - are you just trying to keep track of the stage width?

Ok - I'll give that a shot on Monday when I get back to it.

Learning to do it right the 1st time might be harder, but in the long run it's better... Well that is if I can make the leap.

I'm trying to keep track of the stage width, and set the size or position of some items based on that. The catch for me has been some of those items are in loaded SWF files, so they don't recognize the change in the stage - hence my attempts at creating a global variable for the stage width and passing that into the child SWFs.

If you go back a couple posts of mine, I put a ZIP file with some test FLAs and that class. The FLAs are stripped down so you can see how the SWFs load. Felixz must have grabbed that zip, and seen my horrid attempt at the class.

Yuu
June 30th, 2008, 09:26 AM
ok, I'm back for an all too short weekend... if anyone wants to continue to help me plumb the depths of my lack of knowledge