C#对象引用未设置为对象的实例-但仅当在循环中使用PictureBox数组时



如果我取一些已经存在的图片框,并将它们添加到数组中,Visual Studio就可以了。例如,我可以说trees[64].BringToFront();,它会把图片框放在前面,一切都很好。

然而,当我使用循环将数组中的每个picturebox从开始到结束都放在前面时,它会抛出一个错误。无论我从哪里开始或结束,无论我如何循环,都会给我一个例外。

然而,如果我使用数字而不是int,即使它仍然在循环中,也没关系。我甚至可以告诉for循环在一个任意数字上开始和结束,它会抛出异常,但如果我将完全相同的数字写入picturebox数组(trees[]),它会正常工作。

我只想用一个循环把所有的图片框都放在前面,这是不可能的吗?

此外,如果您想知道try/catch语句为什么是这样的,那是因为图片框排列在11x11网格中

(TA0,TB0,TC0。。。TA1、TB1、TC1。。。TA2、TB2、TC2。。。。。…)
public partial class Form1 : Form
{
    int[] Cell = new int[121];
    public Form1()
    {
        InitializeComponent();
    }
    private void Form1_Load(object sender, EventArgs e)
    {
        Generate();
    }
    private void Generate()
    {
        var trees = new PictureBox[121];
        Random rnd = new Random();
        int n;
        for (int i = 0; i < 10; i++)
        {
            try
            {
                trees[i] = (PictureBox)Controls.Find("TA" + (i).ToString(), true)[0];
                trees[i + 11] = (PictureBox)Controls.Find("TB" + (i + 1).ToString(), true)[0];
                trees[i + 22] = (PictureBox)Controls.Find("TC" + (i + 1).ToString(), true)[0];
                trees[i + 33] = (PictureBox)Controls.Find("TD" + (i + 1).ToString(), true)[0];
                trees[i + 44] = (PictureBox)Controls.Find("TE" + (i + 1).ToString(), true)[0];
                trees[i + 55] = (PictureBox)Controls.Find("TF" + (i + 1).ToString(), true)[0];
                trees[i + 66] = (PictureBox)Controls.Find("TG" + (i + 1).ToString(), true)[0];
                trees[i + 77] = (PictureBox)Controls.Find("TH" + (i + 1).ToString(), true)[0];
                trees[i + 88] = (PictureBox)Controls.Find("TI" + (i + 1).ToString(), true)[0];
                trees[i + 99] = (PictureBox)Controls.Find("TJ" + (i + 1).ToString(), true)[0];
                trees[i + 110] = (PictureBox)Controls.Find("TK" + (i + 1).ToString(), true)[0];
            }
            catch (IndexOutOfRangeException)
            {
                MessageBox.Show("pictureBox does not exist!");
            }
        }
        for(int idx = 0; idx <= 120; idx++)
        {
            n = rnd.Next(1, 3);
            Cell[idx] = n;
            trees[idx].BringToFront();   
        }
    }
}

您在数组中只设置了110 PictureBoxes,但循环通过121。您的第一个for循环需要再进行一次迭代——也就是说,退出条件应该是i < 11,而不是i < 10

按原样,您的代码"跳过"数组位置10、21、32、43、54、65、76、87、98、109和120。如果在第二个循环运行之前在代码中设置一个断点,并检查数组,您将在这些位置看到null值。

错误在第二个循环中正确抛出,一次idx = 10;在该位置没有PictureBox,因此NullReferenceException

您在数组中留下了空白。

想想当i0时会发生什么:为索引0、11、22、33、44、55、66、77、88、99和110处的数组元素设置picturebox。当i小于(但等于)10时,循环运行。因此,的最后一个值是9,它将数组元素的picturebox设置为9、20、31、42、53、64、75、86、97、108、119。

这在阵列中的位置10、21、32、43、54、65、76、87、98、109和120处留下间隙。

您可以通过将<更改为<=或将10更改为11来解决此问题。

谢谢大家!是的,在这个问题上肯定做得很努力。我也在用最低效的方式编写代码,我只是把数字系统改为从左到右,从上到下,只通过数字0到120,而不是字母/数字坐标系,这让我可以用更少的代码对系统做更多的处理。(T0,T1,T2…T119,T120)下面是Generate()方法的一个示例,它给出了在新系统下所做更改的基本概念。

请记住,我已经对代码进行了大量更新,因此这绝不能反映完全更新的系统。在这里,我通过将PictureBoxes层叠在一起来创建动画,然后使用。BringToFront();功能,使每个PictureBox进入视图。目前,无论有多少图像,我都没有使用121个PictureBoxes的次数,而是总共使用121个PictureBoxes,并更改每一个的图像。这样我就不会无缘无故地消耗掉大量的内存。

    var trees = new PictureBox[121];
    Random rnd = new Random;
    for(int idx = 0; idx <= 120; idx++)
    {
    try
    {
    trees[i] = (PictureBox)Controls.Find("T" + (i).ToString(), true)[0];
    }
    catch(IndexOutOfRangeException)
    {
        MessageBox.Show("pictureBox does not exist!");
    }
    Cell[idx] = rnd.Next(1,3)
    if(Cell[idx] == 1)
    {
    trees[idx].BringToFront();
    }
    }

实际代码使用2D阵列(Temp_Record[,]=new int[12121])代替阵列Cell[],从而可以有121个单元的121个屏幕以及称为Master_Record]的相同大小的第二阵列,以在永久值最终确定后存储永久值。Generate()只为每个条目分配一个数字,此时它调用一个名为Draw()的私有void,该void遍历条目,读取数字,然后使用一个长if语句(别担心,在我清理时将其更改为switch语句)遍历每个数字,并将适当的图像应用于与该单元格对应的PictureBox。默认情况下,我称之为"屏幕"是60,如果你想象一个11乘11的网格中的每个11乘11网格的图片框,那么它就是中心。如果有人想要从开始到结束的完整代码,我会发布它,只是在这一点上要长得多。(这是一个简单的自上而下的开放世界游戏)

最新更新