Controls.Remove从控件中删除但不从窗口中删除

时间:2013-11-22 17:24:14

标签: c#

我正在尝试用C#重新创建一个游戏,我有一个由3个对象组成的控件:

  • 带有动画图像[Player]的个性化PictureBox,
  • 另外两个带有球体的动画PictureBox,用于发射[Orbs]。

问题是,我有这段代码:

Orb[,] map = orbsAmmo;

for (Int32 x = 0; x < 2; x++)
    for (Int32 y = 0; y < 2; y++)
        orbsAmmo[x, y] = null;

for (Int32 index = this.Controls.Count - 1; index >= 0; index--)
    if (this.Controls[index] is Orb) {
        this.Controls[index].Parent = null;
        //this.Controls[index].Dispose();
        this.Controls.RemoveAt(index);
    }

//GC.Collect();

return map;

工作正常并从控件列表中删除控件,但应该启动的两个Orb仍在同一位置。如果我试图查看控件列表是否仍然只有Orbs出现播放器的PictureBox。

我添加了GC.Collect();收集垃圾,没有发生任何事情。

这是我没有看到或遗失的东西?


解决

基本上,当我创建Orbs时出现错误,我有Orb.parent = PictureBox正确覆盖图像,因为透明度,并且做了那段代码我不得不从PictureBox中删除Orbs而不是主要控制,就像我试图做的那样。

现在它工作正常。

3 个答案:

答案 0 :(得分:1)

for (Int32 index = this.Controls.Count - 1; index >= 0; index--)
    if (this.Controls[index] is Orb) {
        this.Controls[index].Parent = null;
        //this.Controls[index].Dispose();
        this.Controls.RemoveAt(index);
    }

此代码有问题,会随机删除控件。控件必须拥有父级。如果将其设置为null,则它将从父级的Control集合中删除。现在,您将为另一个控件调用RemoveAt()。这可能是一个不是Orb的控制。

对于控件,调用Dispose()方法是可选的。当您从父母中删除它们时,它们将被重新托管到隐藏的停放窗口。他们住在哪里,准备搬到另一个父母那里。由于这种情况从未发生过,因此您的程序将泄漏控件。这不可能无穷无尽,Windows拒绝让你在消耗10,000个窗口后创建更多的窗口。

与投诉不完全匹配。控件明显消失需要发生的另一件事是父母重新绘制其背景。破碎的绘画在游戏代码中很常见。

答案 1 :(得分:0)

如果你是clearing/disposing index进行控制,那么你肯定会错过其中一些,因为每次你清除/处置一个控件index will be changed

示例:如果您在Control移除index0 - &gt;索引1处的控件变为索引0,因此下次当您尝试在index 1处删除控件时,您将跳过清除index 0处的控件

试试这个:

this.Controls.Clear();

this.ControlPanel.Controls.Clear();

答案 2 :(得分:0)

您可以尝试使用foreachlinq来处置orbs

IEnumerable<Control> c = GetAllOrbs(this);

foreach (Orb item in c.ToArray())
{
    item.Dispose();
    //or if you prefer just to remove them use this:
    //item.Parent.Controls.Remove(item);
}

public IEnumerable<Control> GetAllOrbs(Control control)
{
    var controls = control.Controls.Cast<Control>();

    return controls.SelectMany(ctrl => GetAllOrbs(ctrl, type)).Concat(controls).Where(c => c.GetType() == typeof(Orb));
}

你的问题不清楚,但是从你在代码中看到的你要删除的球体。