无法删除精灵容器的所有图像

发布于 2024-11-08 21:32:25 字数 432 浏览 4 评论 0原文

我有一堆图像。 这些图像全部添加到精灵容器中:

var container:Sprite = new Sprite();
container.addChild(img);//added in a loop
addChild(container);

稍后,当我迭代容器以删除图像时,我说:

for(var i:int=0;i<container.numChildren;i++)
{
     var currImg:Sprite = container.getChildAt(i) as Sprite;
     container.removeChild(currImg);
}

仅删除了部分图像。如果我跟踪container.numChildren,我会得到要删除的正确图像数量。 有人遇到同样的问题吗?

I've got a stack of images.
Those images are all added to a sprite container:

var container:Sprite = new Sprite();
container.addChild(img);//added in a loop
addChild(container);

Later, when I iterate through the container to remove the images I say:

for(var i:int=0;i<container.numChildren;i++)
{
     var currImg:Sprite = container.getChildAt(i) as Sprite;
     container.removeChild(currImg);
}

Only a part of the images are removed. If I trace container.numChildren I get the correct number of images to be removed.
Did someone have the same problem ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

知足的幸福 2024-11-15 21:32:25

尝试以相反的顺序删除它们。您可能会丢失删除,因为您试图在前向循环中删除它们。

for(var i:int=container.numChildren;i>=0;i--)
{
     var currImg:Sprite = container.getChildAt(i) as Sprite;
     container.removeChild(currImg);
}

Try removing them in reverse order. It's possible that your're missing removals because you're trying to remove them while in a forward-bound loop.

for(var i:int=container.numChildren;i>=0;i--)
{
     var currImg:Sprite = container.getChildAt(i) as Sprite;
     container.removeChild(currImg);
}
你怎么这么可爱啊 2024-11-15 21:32:25

我也遇到过这个问题。这里实际上的错误在于,您逐步浏览显示列表并在每次迭代时将其缩小。在 AVM2 中,显示列表深度在此上下文中自动管理,并且当您删除子项时,显示列表深度的其余部分将被调整。无论如何,解决方案是将其包装在 while 循环中:

while(container.numChildren > 0){
    container.removeChildAt(0);
}

更新

还有关于您的代码的注释。尽量不要对剪辑投射新的引用。这将导致闪存虚拟机中的垃圾收集过程出现问题,该过程是自动的,并且只有取消引用或使用弱引用引用的对象才会被清理。因此,您可以执行以下操作之一:

for(var i:int=0;i<container.numChildren;i++)
{
     var currImg:Sprite = container.getChildAt(i) as Sprite;
     container.removeChild(currImg);
     currImg = null;
}

for(var i:int=0;i<container.numChildren;i++)
{
     container.removeChild(Sprite(container.getChildAt(i)));
}

I've encountered this problem as well. What's actually wrong here is that you're stepping up through the display list AND cutting it down with each iteration. In AVM2 the display list depth is automatically managed in this context, and when you remove a child the rest of the display list depth is adjusted. Anyway, the solution is to wrap it up in a while loop:

while(container.numChildren > 0){
    container.removeChildAt(0);
}

Update

Also one note about your code. Try not to cast a new reference to the clip. This will cause issues for the garbage collection process in the flash VM, which is automated and only objects dereferenced or referenced using weak references will be cleaned up. So you can do one of the following:

for(var i:int=0;i<container.numChildren;i++)
{
     var currImg:Sprite = container.getChildAt(i) as Sprite;
     container.removeChild(currImg);
     currImg = null;
}

or

for(var i:int=0;i<container.numChildren;i++)
{
     container.removeChild(Sprite(container.getChildAt(i)));
}
ˇ宁静的妩媚 2024-11-15 21:32:25

这段代码可以工作:

while(container.numChildren > 0)
{
    container.removeChildAt(0);
}

但是我想指出该循环有什么问题,以便您了解发生了什么。将我在下面添加到您的代码中的跟踪添加到您的代码中。 :

for(var i:int=0;i<container.numChildren;i++)
{
     trace (i + " : " + container.numChildren);
     var currImg:Sprite = container.getChildAt(i) as Sprite;
     container.removeChild(currImg);
}

您会看到每次循环时,子级的数量都会按预期减少。

但您需要了解的是,当删除子项时,容器的显示列表会发生非常显着的变化。

下面是运行循环之前显示列表的外观示例——这些列表前面的数字是它们在容器显示列表中的位置。

0-cat
1-dog
2-bird
3-cow
4-elephant
5-clown

现在,第一次通过循环,您删除了 cat,因为它在显示列表上的位置为 0。显示列表现在如下所示:

0-dog
1-bird
2-cow
3-elephant
4-clown

请注意,显示列表索引已根据删除的子项进行了移动。根据设计,显示列表上不能有间隙。

所以,下一次循环时,i 的值为 1——对吧?这意味着“鸟”将从显示列表中删除,而不是狗,这正是您所期望的。

这是下次循环后的显示列表:

0-dog
1-cow
2-elephant
3-clown

所以,是的。其中许多解决方案都将发挥作用。在这种情况下,我建议使用 while 循环。但我认为从这个问题中获得的真正知识是理解这个问题。

This code will work :

while(container.numChildren > 0)
{
    container.removeChildAt(0);
}

However I wanted to point out what is wrong with that loop so you understand what is happening. Add the trace I've added to your code below, into your code. :

for(var i:int=0;i<container.numChildren;i++)
{
     trace (i + " : " + container.numChildren);
     var currImg:Sprite = container.getChildAt(i) as Sprite;
     container.removeChild(currImg);
}

You'll see that each time through the loop the number of children decreases as expected.

But what you need to understand is that when a child is removed -- the display list of the container changes in a very significant way.

Here's an example of how your display list might look before running the loop -- the number I have on the front of these is their position on the container display list.

0-cat
1-dog
2-bird
3-cow
4-elephant
5-clown

Now, the first time through the loop, you remove cat cause it's location is 0 on the display list. Here's what the display list looks like now :

0-dog
1-bird
2-cow
3-elephant
4-clown

Notice that the display list indexes have shifted based on the removed child. There CANNOT be gaps on the display list by design.

so, the next time through the loop, the value of i is 1 -- right ? That means "bird" will be removed from the display list, as opposed to dog, which is what you might have expected.

so here's the display list after that next time through the loop :

0-dog
1-cow
2-elephant
3-clown

So, yes. Many of these solutions will work. In this case I'd recommend the while loop. But I think the real knowledge to be gained from this question is understanding the problem.

萌逼全场 2024-11-15 21:32:25

与@Michael的答案类似,您的原始代码缺少删除,因为您的“numChildren”大小正在减少,并且您的迭代器在每个循环上都在增加:

正如@Ascension Systems指出的,这是最好的方法。

while(container.numChildren > 0){
  container.removeChildAt(0);
}

但是,如果您确实想循环执行此操作,则需要反向执行。

for(var i:int=container.numChildren;i>=0;i--){
  container.removeChild(container.getChildAt(i));
}

为了说明原始代码中发生的情况,请注意以下包含 25 个子项的示例:

如果在前向循环中删除,则会发生以下情况(在每次迭代中):

i:0 Array length:24
i:1 Array length:23
i:2 Array length:22
i:3 Array length:21
i:4 Array length:20
i:5 Array length:19
i:6 Array length:18
i:7 Array length:17
i:8 Array length:16
i:9 Array length:15
i:10 Array length:14
i:11 Array length:13
//the remaining 12 items never get looped over...

Similar to @Michael's answer, your original code is missing removals because your "numChildren" size is reducing and your iterator is increasing on every loop:

As @Ascension Systems noted, this is the best approach.

while(container.numChildren > 0){
  container.removeChildAt(0);
}

However if you do want to do it in a loop, you'll need to do it in reverse.

for(var i:int=container.numChildren;i>=0;i--){
  container.removeChild(container.getChildAt(i));
}

To illustrate what happens in your original code, note the following example with 25 children:

If you remove in a forward loop this is what happens (on each iteration):

i:0 Array length:24
i:1 Array length:23
i:2 Array length:22
i:3 Array length:21
i:4 Array length:20
i:5 Array length:19
i:6 Array length:18
i:7 Array length:17
i:8 Array length:16
i:9 Array length:15
i:10 Array length:14
i:11 Array length:13
//the remaining 12 items never get looped over...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文