PDA

View Full Version : RemoveChild Errors


ajwei810192
03-01-2010, 06:52 PM
Hi,

I have the code as in the following, and I am attempting to remove the child, and then create a new one with a different type for a different purpose. The child, however, does not seem to be able to be removed, below is the code:


package map
{
import com.zavoo.svg.*;
import flash.display.Sprite;
import flash.events.Event;
import mx.containers.Canvas;
import mx.core.UIComponent;

public class SvgMap extends UIComponent {

public var canvas:Sprite;
[Embed(source="USA_Counties_with_FIPS_and_names.svg")]
public var usaMap:Class;
private var horizontal_bar:Canvas;

public function SvgMap():void {

canvas = new usaMap();
canvas.width = 650;
canvas.height = 500;
addChild(canvas);
trace(canvas.parent); //Prints out SvgMap0 SvgMap4 SvgMap7
}

public function changeMap():void{

trace(canvas.parent); //Prints out SvgMap4
removeChild(canvas);
if(canvas)trace("Canvas"); //Always prints out canvs
else trace("No Canvas");

}
}
}


Could anyone please provide some clues on what I might have done wrong here? Why is it that I could not remove the child?

Thanks for your help.

maskedMan
03-01-2010, 07:08 PM
You aren't going to lose the reference to canvas just because you remove it from the display list.

if(canvas)

will always return true unless you explicitly set canvas = null.


Try this test:



if(canvas){
if(canvas.parent) trace("canvas has a parent");
if(canvas.stage) trace("canvas is on the display list");
}

ajwei810192
03-01-2010, 07:15 PM
Weird, when I run this test

public function changeMap():void{

removeChild(canvas);
if(canvas == null) trace("There is no canvas");
else {
if(canvas.parent) trace("canvas has a parent");
if(canvas.stage) trace("canvas is on the display list");
else trace("Everythig else"); //I get this
}
}


I get the result from the last else in the else statement, so this means that it is not on stage, and has no parent. So, this means that I had deleted entirely, but how am I supposed to use that name to create a type object, like a sprite?

BTW, if I had deleted the canvas, which in this case is the usaMap() as defined in


public function SvgMap():void {

canvas = new usaMap();
canvas.width = 650;
canvas.height = 500;
addChild(canvas);
trace(canvas.parent);
}


Then, how could I possibly be still able to see the map?

maskedMan
03-01-2010, 07:21 PM
Not weird at all. Try this as further clarification:


public function changeMap():void{

removeChild(canvas);
if(canvas){
trace("I have access to a canvas : "+canvas);
if(canvas.parent) trace("canvas has a parent");
else trace("canvas does not have a parent");
if(canvas.stage) trace("canvas is on the display list");
else trace("canvas is not on the display list");
}
else trace("There is no canvas");
}


EDIT: I expect the output is:

"I have access to a canvas : (your canvas)"
"canvas does not have a parent"
"canvas is not on the display list"

Canvas may still have a parent even if it is not on the display list. Parent/child relationships are maintained in memory, after all.

I'd be worried if canvas does not have a parent, but it IS on the display list. That would probably be a sign of the coming apocalypse.

ajwei810192
03-01-2010, 07:32 PM
What I am trying to do here is to remove the child so that I cannot see the map as I have declared in


public function SvgMap():void {

canvas = new usaMap();
canvas.width = 650;
canvas.height = 500;
addChild(canvas);
}


This is what I got using the code from your test:

I have access to a canvas : SvgMap_usaMap5

So, I still have not removed the child, or have I?

maskedMan
03-01-2010, 07:47 PM
So wait... you don't see the other trace statements at all? "canvas" exists, but it neither has nor does not have a parent or a stage? Try copy/pasting the whole of the debug code again.

ajwei810192
03-01-2010, 07:54 PM
Yeah, I did find the longer code that you provided in message #4, and my output is as you anticipated. Here it is:

I have access to a canvas : SvgMap_usaMap5
canvas does not have a parent
canvas is not on the display list

However, I can still see the image, which was defined as the name, canvas after the code has been run. This is where I had defined the canvas to begin with:


public function SvgMap():void {

canvas = new usaMap();
canvas.width = 650;
canvas.height = 500;
addChild(canvas);
}


Is this weird, or what? I am getting confused.

maskedMan
03-01-2010, 08:03 PM
What you see in the Flash Player is *very* weird, and given what we know right now it can mean only one thing:

The image you are seeing in the Flash Player is *not* canvas.

Somehow, you've got a completely different object hanging out onstage, with the exact same appearance as your canvas. Something I find useful to do when supreme weirdness like this happens is to set up a recursive function that trace out the entire contents of the display list in the format of...

indentation + obj.toString() + obj.name (only if the object *has* a name property)

It's not difficult to make such a function (shouldn't be more than 15 lines of code at most), but I don't have a lot of time to give an example of it.

bocasz
03-01-2010, 08:10 PM
you can use De MonsterDebugger (http://demonsterdebugger.com/) to see everything that is in the stage.
Its a really nice debugging app.

henke37
03-01-2010, 08:56 PM
All display objects have a name property. And it's set too. The issue is that a lot of the names are useless auto created ones.

ajwei810192
03-01-2010, 09:22 PM
OK, I think I might know why I cannot remove the child. However, again, I am not sure how I can fix this.

This is the package that is called by the main application on Flex,


package map
{
import colorize.*;
import com.zavoo.svg.*;

import flash.display.Sprite;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;

import mx.containers.Canvas;
import mx.core.UIComponent;

public class SvgMap extends UIComponent {

public var canvas:Sprite;
[Embed(source="USA_Counties_with_FIPS_and_names.svg")]
public var usaMap:Class;
public var paths:SvgPaths;

public function SvgMap():void {

canvas = new usaMap();
canvas.width = 650;
canvas.height = 500;
addChild(canvas);
}

public function changeMap():void{

removeChild(canvas);
if(canvas){
trace("I have access to a canvas : "+canvas);
if(canvas.parent) trace("canvas has a parent");
else trace("canvas does not have a parent");
if(canvas.stage) trace("canvas is on the display list");
else trace("canvas is not on the display list");
}
else trace("There is no canvas");

canvas = new Sprite();
addChild(canvas);

}
}
}


This is my main app:


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="100%"
height="100%" creationComplete="addsvgMap()">
<mx:Script>
<![CDATA[
import mx.events.SliderEvent;
import mx.events.FlexEvent;
import com.zavoo.svg.*;
import flash.display.Sprite;
import colorize.*;
import map.SvgMap;
import flash.events.Event;
import flash.display.Graphics;
import mx.events.SliderEvent;
import mx.core.IUIComponent;

public var thematicColorize:Thematiccolorize = new Thematiccolorize();
public var sliderCal:Slider = new Slider();
public var svg:SvgMap = new SvgMap();
public function addhorizontalbar():void{ vbox.addChild(sliderCal); //By this time, slider and horizontal bar has been created, no map
}

public function addsvgMap():void{
horizontal_bar.addChildAt(svg,0);
trace(horizontal_bar.numChildren); //return 1, should it not be 2?
}

]]>
</mx:Script>

<mx:VBox id="vbox" x="20" y="10">
<mx:Canvas id="horizontal_bar" width="350" height="520" creationComplete="addhorizontalbar()" />
</mx:VBox>
</mx:Application>


So, I don't think under this circumstance, not even the "parent" is the same. Or, am I wrong?

This is confusing.

maskedMan
03-01-2010, 09:28 PM
All display objects have a name property. And it's set too. The issue is that a lot of the names are useless auto created ones.

Not Shape objects. Try tracing shape.name

ASWC
03-01-2010, 09:33 PM
Let's go to Flex forum boys! ;)

ASWC
03-01-2010, 09:36 PM
Not Shape objects. Try tracing shape.nameWhat do you mean? I just checked the docs and name property is there for Shape (and why wouldn't it be since name is a property from DisplayObject?).

maskedMan
03-01-2010, 10:07 PM
What do you mean? I just checked the docs and name property is there for Shape (and why wouldn't it be since name is a property from DisplayObject?).

Looks like I was mistaken, then? :) It's been a while since I wrote the function and I excluded shapes for a reason that I forgot at the time. I thought it was because of an error with Shape not having a name, but I didn't include any special error handling for the occasion.

I think the reason I excluded Shapes was because they were cluttering up my output and I didn't really care about them after all.

If you want to ignore the "useless" instance names, you can do a match to see if the displayObject.name starts with "instance", as Flash always gives its unnamed display objects a name of "instance"+someNumber.... Of course, if *you* start your instance names with the word "instance" then you'll have a little bit of a trickier time with this. ;)

ajwei810192
03-02-2010, 01:28 AM
So I guess you guys think this is a Flex problem?
All right, I will send this post over and see what they would suggest.

I am surely bummed out by this problem.
Thinking you have deleted some child in a container but you didn't because the instance is difference is surely driving me crazy.

ASWC
03-02-2010, 02:05 AM
I'm glad to see somebody using short if else writing that completely messes up the whole code! You really do think this is only gonna add the canvas back with your else?
else trace("There is no canvas");

canvas = new Sprite();
addChild(canvas);
No chance whenever this code runs you add canvas back to the displaylist. So your function right now removes canvas and then add it back which is what we would call an useless function. So basically JUST because you want to use shortened if else writing you spent hours trying to figure out what is wrong! Some people like me will never run into this problem ...

ajwei810192
03-02-2010, 03:02 AM
My adding a new sprite is supposed to be used for creating a new drawing area that is "blank", and not that I am adding the "old canvas with the image" back. That is, to remove the child "canvas", one that has the usaMap class, and since it is removed, I will add a new drawing "Sprite" to the container so that I can do something with it later.

Sorry about my short statements. But, how does this mess it up? This is what I am trying to do:


else {trace("There is no canvas");}
canvas= new Sprite();
addChild(canvas);

drkstr
03-02-2010, 05:56 AM
May I suggest...

package map
{
public class SvgMap extends Image {

[Embed(source="USA_Counties_with_FIPS_and_names.svg")]
public var usaMap:Class;

[Embed(source="CANADA_Counties_with_FIPS_and_names.svg")]
public var canadaMap:Class;

public function SvgMap():void {
this.source = this.usaMap;
}

public function changeMap():void{
this.source = (this.source == usaMap)?
this.canadaMap : this.usaMap;
}
}
}

Flex eliminates the need for you to have to do low level things like control your image assets on the display list. Only use Sprites for chrome, which should be added to rawChildren.

To find out why your having this "unexpected" behavior, turn on the keep-source option and see how Flex manages these assets. There is a lot going on there...


Cheers!

ajwei810192
03-02-2010, 03:43 PM
Hi,

Image is not going to work, because I have to use the same canvas to load httpservice.

Since I expected this to only be "triggered" when a user moves the slider, I moved the function of what I intended to do from the beginning to the class where a slider is. This actually took me some variables passing around between main and child classes. However, it looks like the "child" is called as I had expected. Strangely, I still could not delete the child directly, since I got error #2025 with the supplied DisplayObject must be a child of the caller. I solved the problem eventually, by deleting this child from the parent:

BTW, the code is in the following:


private var childname:DisplayObject;
public function changeData(e:Ev
ent):void{
if(horizontal_bar) trace("Test Only " + horizontal_bar.getChildAt(0));

childname = horizontal_bar.getChildAt(0);
trace("Parent " + childname.parent);
childname.parent.removeChild(childname);
if(childname){
trace("I have access to a canvas : "+ childname);
if(childname.parent) trace("canvas has a parent");
else trace("canvas does not have a parent");
if(childname.stage) trace("canvas is on the display list");
else trace("canvas is not on the display list");
}
else trace("There is no canvas");
}


The output:

Test Only main9.vbox.horizontal_bar.SvgMap7
Parent main9.vbox.horizontal_bar
I have access to a canvas : SvgMap7
canvas does not have a parent
canvas is not on the display list

You guessed it, the image that has been driven me nuts all this time has left the screen. :cool:

Thanks!

drkstr
03-02-2010, 08:48 PM
Image is not going to work, because I have to use the same canvas to load httpservice.

FYI, Image handles all that for you as well.

this.source = "http://localhost/some_image.svg";

Bam, done! Loading, display list, everything.

If the default functionality doesn't work for you, you can extend and override.


But if you are adamant about doing it the hard way, I'm no one to stop you.


Cheers!