Call to possibly undefined method dispatchEvent through a reference with static type GetColor - actionscript-3

I'm writing a program using Main.as, that needs to listen to a function (getColor) in another class file (GetColor.as). I have the following in GetColor.as:
public class GetColor
{
public function getColor(event:MouseEvent):void
{
//doing stuff here
this.dispatchEvent(new Event("changeColor") );
}
}
and then in Main.as I have:
var getPicColor:GetColor = new GetColor();
getPicColor.addEventListener("changeColor",changeColorNow);
function changeColorNow(e:Event):void
{
//do stuff here
}
However, I am getting an error:
1061: Call to a possibly undefined method dispatchEvent through a reference
with static type GetColor.
What does this mean? I have nothing declared as static. Am I supposed to create an instance of dispatchEvent(), as opposed to using "this"?

You cannot dispatch events with a class that (implicitly) extends Object -> that's why you are getting there error -> where is "dispatchEvent()" method coming from? Where is it inherited from? (answer: it is not!)
Your GetColor class (horrible name there! :) ) must either extend a display object - which in your case it not really the correct solution, extend EventDispatcher or implement IEventDispatcher.
Then you can use the method dispatchEvent.

Related

When using the 'Class' datatype, how can I specify the type so I only accept subclass of a specific class?

I've got a method that accepts a parameter of type Class, and I want to only accept classes that extend SuperClass. Right now, all I can figure out to do is this, which does a run-time check on an instance:
public function careless(SomeClass:Class):void {
var instance:SomeClass = new SomeClass();
if (instance as SuperClass) {
// great, i guess
} else {
// damn, wish i'd have known this at compile time
}
}
Is there any way to do something like this, so I can be assured that a Class instance extends some super class?
public function careful(SomeClass:[Class extends SuperClass]):void {
var instance:SuperClass = new SomeClass();
// all is good
}
If you are going to instantiate it anyway, why not accept an object instead which allows you to type it to :SuperClass?
careless(SomeClass);
//vs.
careless(new SomeClass);
Not too much of a problem there as far as your code goes.
There are a few differences though:
The object has to be created, because an object is required. If your function does not instantiate the class under some circumstances, this can be a problem. Additional logic to pass either an object or null can bloat the function call.
If you cannot call the constructor outside that function, it won't
work either.
All that is solved by the factory pattern. Pass a factory as the parameter that produces SuperClass objects.
function careful(factory:SuperClassFactory)
Your requirements:
I want to only accept classes that extend SuperClass
and
I need to pass in a Class so that it can be instantiated many times
by other objects later
Can be met by passing in an instance of the class you need, and using the Object.constructor() method.
public function careful(someInstance:SuperClass):void {
//you probably want to store classRef in a member variable
var classRef: Class = someInstance.constructor();
//the following is guaranteed to cast correctly,
//since someInstance will always be a descendant of SuperClass
var myInst:SuperClass = new classRef() as SuperClass;
}
More reading here.
You can't do that in ActionScript 3. In languages like C# you can do something like (forgive me if the syntax is off):
public void Careless<T>() where T : SuperClass
But AS3 does not have 'generics'. Unfortunately the only way I know how to do what you want is the way you have already done.
A pattern that might be more suitable for your use case might be something like:
class SuperClass
{
public static function careless():void
{
var instance:SuperClass = new SuperClass();
// ...
}
}
The only way to have static type checking in ActionScript 3 is to provide an instance of a class.
It is possible but it's expensive. You can use on a Class (not instance) the:
flash.utils.describeType
You then get an XML with a bunch of information including inheritance for that class. Like I said it's an expensive process and probably creating an instance and checking it will be in most cases faster.

How do one cast a instance of subclass to its superclass?

So I have this superclass grid class, and a subclass of the grid class named GrassTile1, GrassTile2, etc... all of the instance of the subclasses are stored in an array. How am I suppose to convert the instance of subclass to its superclass referencing to the array?
private var backgroundGrid = []; //the array which the grids are stored in, in the main class.
public class Grid extends MovieClip
{
protected var node :PathfindNode; //the variable I wish to access, from an instance of subclass.
public function Grid(){
node = new PathfindNode();
}
}
public class GrassTile1 extends Grid { //every subclass of Grid will extends Grid
public function GrassTile1() {
// constructor code
}
}
function getBackgroundGrid(i:int,j:int):Grid{ //in the main class
return Grid(backgroundGrid[i][j]); // this line gives me an error
}
TypeError: Error #1034: Type Coercion failed: cannot convert GrassTile1#2905d5f1 to Grid.
I've tried accessing backgroundGrid[i][j].node and other ways to work around that I could think of and failed. Any Idea?
Try :
return backgroundGrid[i][j] as Grid;
Personally, Grid seems like a bad class name to use. I think Tile makes more sense, as that GrassTile1 is not a grid as I logically understand a grid. A grid might contain a collection of tiles, so doesn't sound logical to use that as a class name for tiles.
Also, where is the line where you actually call the getBackgroundGrid method ? You should try casting there, as opposed to in that method. I believe that will solve the problem.
I can't verify the line throwing the error, so we are assuming that it's the return statement. But, it could be on the other side where you are calling getBackgroundGrid.
UPDATE : I have tried a .fla using what you are describing and it works just fine, I get no error. Which is why I'm thinking we are missing something here and maybe the definition of the class is not being used. Can you put a trace in your constructors to verify what you expect is actually happening ?

compiler error when trying to use addEventListener via interface

Trying to use addEventlistener with an interface, but i get a compiler error :
=> Call to a possibly undefined method addEventListener through a reference with static type IScene.
//IScene.as
public interface IScene
{
function show():void
function load():void;
function unload():void;
}
//Main.as
var scene:IScene ;
scene= sceneView_Arr[scene_number] ;
scene.addEventListener( GameEvent.ON_LOAD_SCENE , start );
scene.load();
scene.show();
How should i achieve it then ?
Instead of Fox in socks answer, I would recommend a slightly different approach:
public interface IScene extends IEventDispatcher
And then for your actual scene classes
public class MyScene extends EventDispatcher implements IScene
And then you can use it as you already have, without any additional code.
scene.addEventListener(GameEvent.ON_LOAD_SCENE, start);

Flash AS3 Dyanmic Text keeps giving an error 1119

So I have a method that takes in a String and then is suppose to set the dynamic textbox on a button to said String.
public function setText(caption:String) {
this.btext.text = caption;
}
I really don't understand why this method is producing a 1119 error.
Access of a possibly undefined property btext through a reference with static type Button.as
The instance name of the Dynamic Textbox is btext and I have tried deleting the textbox and making a new one however this still produces a 1119 error. I also read on another stack question that trying this['btext'].text = caption; which gave me plenty of runtime errors.
Basically what am I doing wrong?
Thank you for any help.
EDIT
Here is the code I am using, and I create an instance of button add it to the stage and store it in an array with this code.
Code to create button
this.buttonArray.push(this.addChild(weaponButton));
Button.as
package {
import flash.display.MovieClip;
import flash.filters.*;
public class Button extends MovieClip {
public function Button() {
}
public function setPosition(xpos:int, ypos:int) {
this.x = xpos;
this.y = ypos;
}
public function setScale(xScale:Number, yScale:Number) {
this.scaleX = xScale;
this.scaleY = yScale;
}
public function addDropShadow():Array {
var dropShadow:DropShadowFilter = new DropShadowFilter(2,45,0, 1,4,4,1,1,true);
return [dropShadow];
}
public function removeDropShadow():Array {
return null;
}
public function setText(caption:String) {
this.btext.text = caption;
}
}
}
As you have stated btext is an instance name of an object. Here is where I assume btext is an object you created in your library.
In your class you are doing 2 things wrong. So lets examine your method.
public function setText(caption:String) {
this.btext.text = caption;
}
The first thing wrong is you are using "this". "this" is a reference to the current instance of the class you are in. And you are saying btext is a property on said instance. Which as I am assuming it is not because you defined btext as an object in your library. This will give you the property is undefined error you are gettting.
Now the second issue at hand is you are about to ask "OK how do I reference btext in my class then". What you need to know is that only objects added to the display list IE:stage can access objects via the stage.
You can do this 3 ways.
The first way is to pass a reference to the button into the class and store it as a property of the class.
The second way is to add your class to stage and in the class listen to the addedToStage event. At that time you can then access the object.
MovieClip(root)["btext"].text
The first 2 methods are not good practice since btext is not apart of the class and a general rule of thumb would be to encapsulate your class.
To make this work what you could do is have your class assign the value to a property in your class then fire an event and make the parent of this class listen to that event then just grab the value and assign.
Here is some suggested reading
I think the variable btext doesn't exist at all, or is it inherited from Movieclip?

How can i use object from a lazy loaded swf file if the class definition needs to be changed?

I am converting all embed statements in my site with lazy loading. The code which was previously like this:
[Embed(source="/newswf.swf", symbol="kungfu")]
public static var Kungfu:Class;
has now been converted to this form:
private var _loader:Loader = new Loader();
public static var abcd:Class = null;
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onLoadComplete);
_loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS,onProgressHandler);
_loader.load(new URLRequest("newswf.swf"));
private function onLoadComplete(evt:*):void
{
abcd = evt.target.applicationDomain.getDefinition("kungfu") as Class;
dispatchEvent(new MyEvent(MyEvent.LOADING_DONE));
}
The functions which make use of abcd will be called on recieving MyEvent.LOADING_DONE event.
Now, my problem is, when a class makes use of symbol and has a class definition, I am not able to implement it using the above method because the constructor will be called immediately and won't listen to the onLoadComplete event listener.
[Embed(source="/newswf.swf", symbol="judo")]
public class Judo extends MovieClip
{
public function Judo()
{
super(...);
}
}
When i put the code in the constructor in a separate function and calling it in onLoadComplete method, I get an error because super method had initially been used in the constructor and it cannot be used outside of a constructor.
Can someone tell me a way to do lazy loading in this case?
Thanks in advance :)
I'm not sure if it is possible to extend the class definition after loading because I've never tried, but have you tried simply casting the loaded object and then not calling super() again? That is, inside the loader function type:
obj:Judo = Judo(LoaderInfo(e.target).content)
This article may be helpful: http://www.parorrey.com/blog/flash-development/as3-loading-external-swf-into-movieclip-using-loader-class-in-flash-actionscript3/
That said, I probably wouldn't structure the code in this way and just avoid the situation you're describing with a different structure. Like, one approach would be instead of making the loaded object into a Judo object I would initialize a separate Judo object and then pass it the loaded object. The old "has-a" vs. "is-a" distinction.
Another approach that accomplishes the same thing would be for the containing class to not do the loading and simply create a new Judo object, passing the filename into the constructor. Then the Judo object does the loading.