i've a problem to a set a different child index of a Movieclip. This is the code:
function processMusica():void
{
var loadStatus:int=0
var lastHeight:int=0
for (var m=0; m < myXML.BLADE[sup].child("brano").length(); m++)
{
var titolobrano:TextField=new TextField
bladearray[sup].contenitore.addChild(titolobrano)
titolobrano.text=myXML.BLADE[sup].brano[loadStatus].titolo
lastHeight=titolobrano.height
titolobrano.doubleClickEnabled=true
titolobrano.addEventListener(MouseEvent.DOUBLE_CLICK, riproducibrano)
loadStatus+=1
}
if (isPlaying==false)
{
var riproduzioneDetails:MovieClip=new MovieClip
riproduzioneDetails.name="riproduzioneDetails"
var artista:TextField=new TextField
artista.name="artista"
bladearray[sup].contenitore.addChild(riproduzioneDetails)
riproduzioneDetails.x=475
riproduzioneDetails.addChild(artista)
}
setChildIndex(bladearray[sup].contenitore.riproduzioneDetails, bladearray[sup].contenitore.numChildren-1) //<------ PROBLEM HERE!
I want to move "riproduzioneDetails" MC on foreground, but when i attempt to launch application, it give me this error: TypeError: Error #2007: Parameter child must be non-null
I can see two potential problems, but it is hard to say because all the variables are not declared in your code. There may be a problem with your test condition:
if (isPlaying==false)
{
...
}
If "isPlaying" is true, your object "riproduzioneDetails" is never created, so of course it will be null. You have to create your object outside the "if" condition, before testing "isPlaying".
Another potential problem is the way you access your object, with "bladearray[sup].contenitore.riproduzioneDetails". As you used the "addChild" method to store your object, there should logically be a kind of "getChild" method. For instance,
setChildIndex(bladearray[sup].contenitore.getChildByName("riproduzioneDetails"),bladearray[sup].contenitore.numChildren-1)
... may be better.
Related
I am a baffled noob here. I have the following code:
var mC:mc = new mc();
I do NOT instantiate mC at all with an addChild(mC);
But, later in the code, I have a loop using onEnterFrame and in this loop I have the following trace function:
if(mC){
trace("mC is here");
}
This returns "mC is here" in the output window. HUH???
The problem is that I want to use this 'if' statement to removeChild(mC); [I will be adding it in the code later with an addChild(mC); based on certain stuff that happens] but it keeps throwing dang "ERROR child of the caller" messages even with the 'if' condition...
WHAT am I doing wrong? I did not know declaring variables would add them to the stage/display list, I thought you needed an addChild(); statement. Am I smoking something I shouldn't be?
Thanks in advance, ~Frustrated Inc.
When you new up an object it exists in memory, even if you have not added it to the stage. That is why when you check if mC exists, it returns true. You want to check if it exists on the stage. Something like:
var mc:MovieClip = new MovieClip();
mc.name = "test";
if (this.getChildByName("test") != null) {
trace("mc is on stage");
}
I have not used Flash for a long time, so I did not test this code. Hopefully it works.
Complex objects in AS3 (that means anything that is not a string or a number) have a default value of null. WHen evaluated that default value of null equals false:
var mymc:MovieClip;//that MC is NOT instantiated yet so it has a default value of null
if(mymc)
{
//mymc is null so this evaluates to false
//and this statement DOES NOT execute
Now when a complex object is instantiated and exist its value would now evaluates to true
var mymc:MovieClip = new MovieClip();//that MC IS instantiated
if(mymc)
{
//mymc exits so this evaluates to true and this statement EXECUTE
//notice that "!= null" is not necessary
Now your problem has to do with display list. A DisplayObject has a parent property that is null when that object is not added to a display list, and that property point to the parent when that object is added to a display list:
var mc:MovieClip = new MovieClip()
trace(mc.parent);//this is null
addChild(mc);
trace(mc.parent);//this is not null anymore and points to the parent
SO what you mean to do is:
if(mC.parent){//this means mC has a parent and can be removed from it
trace("mC is here");
}
In your code, you just control whether your variable is null or not.
You can use contains method on the display object you are trying to add to.
If you are adding mC to some sprite named container, you can simply check whether it exists in that container with:
if (!container.contains(mC))
container.addChild(mC);
Edit: The safer method to control whether a movieclip is on the stage is to control its stage value.
if (mC.stage) {
mC.parent.removeChild(mC); // this is how you remove, if you simply want to check existence, don't remove it
}
It has to have a stage value if you added the movieclip to the stage or a container that is added to stage.
Hope it is clearer this way.
function addEffect()
{
var thisEffect = new MyEffect; //Simple movieClip
addChild(thisEffect);
effectArray[0] = thisEffect;
}
the above works fine. And later I remove it... The Below works fine also.
function removeEffect()
{
if(effectArray[0] != null)
{
removeChild(effectArray[0]);
}
}
However, after I use the functions again, somtimes the next turn, sometimes two turns later I get:
Error #2025: The supplied DisplayObject must be a child of the caller.
Oddly, I'm using the same technique to add and remove other movieclips, and it is working fine for everything else. I am not referencing the effectArray or anything inside it, outside of these two functions, which are both inside Main.as
That's quite normal.
When you add myEffect to array, only a reference to myEffect is stored in the array.
And when you try to reach that object by array, everything works correct, and reference to myEffect in array points to object correctly each time.
But what is not going right each time is whether there is an object where the reference points or not. If it has deleted, it cannot be child of the target object no more, so you'll get that error.
What you do in removeEffect function is to check if the reference is there, not the object. And reference is always there if you do not remove it from your array. After you remove the object, remove the reference also. And everything will work correct.
function removeEffect()
{
if(effectArray[0] != null)
{
removeChild(effectArray[0]);
effectArray[0] = null;
}
}
Inside my classes, I invoke this function
MovieClip(root).increaseScore();
which handles the score in the main .as file.
It all works fine during the execution of the level. However when the level is finished and the screen goes to another frame, the game crashes and gives me this error
TypeError: Error #1009: Cannot access a property or method of a null
object reference.
on the line above.
How do I fix this?
Thanks
edit:
This is were I tell it to addScore, this is in the GameController.as file
private function removeBubble(bubble, addScore:Boolean)
{
var delay:Timer = new Timer(200, 1);
delay.addEventListener(TimerEvent.TIMER_COMPLETE, function(e:TimerEvent)
{
if(bubble.parent==mcGameStage)
{
var j:int = bubbleList.indexOf(bubble);
bubbleList.splice(j,1);
if(addScore) bubble.addScore();
mcGameUI.txtScorePlayer.text = String(playerScore);
mcGameStage.removeChild(bubble);
}
e.currentTarget.removeEventListener(e.type, arguments.callee);
checkWin();
});
delay.start();
}
here is the checkWin function:
private function checkWin()
{
if (playerBlue + playerRed + playerYellow + playerOrange + playerPurple + playerGreen == 0)
{
gameWin();
}
}
private function gameWin()
{
while (bubbleList.numChildren > 0)
{
bubbleList.removeChildAt(0);
}
mcGameUI.btnMixBlue.removeEventListener(MouseEvent.CLICK, mixBlue);
mcGameUI.btnMixRed.removeEventListener(MouseEvent.CLICK, mixRed);
mcGameUI.btnMixYellow.removeEventListener(MouseEvent.CLICK, mixYellow);
mcGameUI.btnNeedle.removeEventListener(MouseEvent.CLICK, activateNeedle);
mcGameStage.removeEventListener(Event.ENTER_FRAME,update);
mcGameStage.removeEventListener(MouseEvent.CLICK, checkToHit);
removeEventListener(Event.ADDED_TO_STAGE, gameAddedToStage );
stage.removeEventListener(KeyboardEvent.KEY_DOWN,keyDownHandler);
stage.removeEventListener(KeyboardEvent.KEY_UP,keyUpHandler);
if (mouseCursor != null)
{
mouseCursor.removeEventListener(Event.ENTER_FRAME,followMouse);
mouseCursor = null;
}
gotoAndPlay("level1win");
}
And inside my classes,
public function addScore()
{
root["increaseScore"]();
}
This is what increaseScore does
public function increaseScore()
{
playerScore += 1000;
}
So where is the null object? D:
Also I am very inexperienced using the debugger so I apologize if this could be easily solved with that. I tried it and couldn't figure it out before coming here.
What is OPP method?
What is FrameScript?
Also, the class is MovieClip
thanks :)
Fixing this is done with the help of the debugger!
The error is telling you that something is null and you're trying to access it. That's not good, so let's think what could be null?
1) Your movie clip instance might be null.
2) increaseScore() method of your movie clip instance might try to access something that is null
You didn't post any code that I could analyse at the time I'm writing this answer, so I can't say for sure.
Some possible problems:
Your class is not called MovieClip, but you're just trying to cast your root object to a MovieClip. Thing is, MovieClip's don't have a increaseScore() method. You should instead call the increaseScore() method with
root["increaseScore"]();
This will call the method of your root timeline, but since we are using weak-typing, you might have problems with debugging it later. But I guess that's the price you pay when writing all the code in a frame instead of using OPP approach.
The true reason here is said in the error: Cannot access a property or method of a null object reference.
What this means is that MovieClip(root) is null (it doesn't even bother to check if the function is present). The reasons for this might be three:
Your document class is not MovieClip (could be Sprite).
The class you use root in, is not DisplayObject. The property is part of the DislpayObject class and so if you use it on other kind of classes that does not extend it, it won't work.
You are using this piece of code before you have added the instance to the stage (most probable cause). The root property represents the top-most display object in the tree. If you haven't added the child to the tree, it has no roots :) Check out parent - the error should be the same.
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.
I have a movieclip in the library that is added to the stage dynamically in the document class's actionscript. This movieclip contains many many child images that were imported directly from photoshop at their original positions (which must be preserved).
I do not want to manually name every single image instance, as there are dozens upon dozens.
I have already gone through and manually converted the images to symbols, as apparently flash won't recognize the "bitmap" objects as children of a parent movieclip in AS3 (numChildren doesn't see the bitmaps, but it sees the symbols).
I have an array filled with references to the dozens of children, and I loop through it, checking if each one is under the mouse when clicked. However, somehow, it is not detecting when I click over the items unless I manually name the child symbols (I tested by manually naming a few of them -- those ones became click-sensitive.)
I have already done trace() debugging all throughout the code, verifying that my array is full of data, that the data is, in fact, the names of the instances (automatically named, IE instance45, instance46, instance47, etc.), verifying that the function is running on click, verifying that the code works properly if I manually name the symbols.
Can any one see what's going wrong, or what aspect of flash I am failing to understand?
Here is the code:
//check each animal to see if it was clicked on
private function check_animal_hits():void
{
var i:int = 0;
var animal:Object = this.animal_container;
for (i=0; i<animal.mussels.length; i++)
{
if (this.instance_under_cursor(animal.mussels[i].name))
{
var animal_data = new Object();
animal_data.animal = "mussel";
this.send_data(animal_data);
}
}
}
Here is the code for the instance_under_cursor() method:
// Used for finding out if a certain instance is underneath the cursor the instance name is a string
private function instance_under_cursor(instance_name)
{
var i:Number;
var pt:Point = new Point(mouseX,mouseY);
var objects:Array = stage.getObjectsUnderPoint(pt);
var buttons:Array = new Array ;
var o:DisplayObject;
var myMovieClip:MovieClip;
// add items under mouseclick to an array
for (i = 0; i < objects.length; i++)
{
o = objects[i];
while (! o.parent is MovieClip)
{
o = o.parent;
}
myMovieClip = o.parent as MovieClip;
buttons.push(myMovieClip.name);
}
if (buttons.indexOf(instance_name) >= 0)
{
return true;
}
return false;
}
Update:
I believe I have narrowed it down to a problem with getObjectsUnderPoint() not detecting the objects unless they are named manually.
That is the most bizarre way to find objects under mouse pointer... There is a built-in function that does exactly that. But, that aside, you shouldn't probably rely on instance names as they are irrelevant / can be changed / kept solely for historical reasons. The code that makes use of this property is a subject to refactoring.
However, what you have observed might be this: when you put images on the scene in Flash CS, Flash will try to optimize it by reducing them all to a shape with a bitmap fill. Once you convert them to symbols, it won't be able to do it (as it assumes you want to use them later), but it will create Bitmpas instead - Bitmap is not an interactive object - i.e. it doesn't register mouse events - no point in adding it into what's returned from getObjectsUnderPoint(). Obviously, what you want to do, is to make them something interactive - like Sprite for example. Thus, your testing for parent being a MovieClip misses the point - as the parent needs not be MovieClip (could be Sprite or SimpleButton or Loader).
But, if you could explain what did you need the instance_under_cursor function for, there may be a better way to do what it was meant to do.