如何创建PictureBox数组并使用?代码空引用异常求解
解决PictureBox数组空引用异常及动态创建控件的正确方式
问题原因
- 你声明的
Brickn() As PictureBox只是一个数组变量,未初始化实际的数组实例,此时数组处于Null状态,直接通过索引访问Brickn(NoOfBrick)会触发NullReferenceException。 - VB.NET中数组必须先通过
ReDim指定长度才能使用,你缺失了这一关键步骤。
解决方案:两种实现方式
方式1:使用动态调整长度的数组(ReDim Preserve)
每次添加新控件前,重新调整数组长度并保留已有元素:
Dim brickWidth As Integer = 0 Dim Brickn() As PictureBox Dim NoOfBrick As Integer = 0 ' 初始化索引计数 Public Function CreateBrick() As PictureBox Dim myBrickn As New PictureBox With myBrickn .Size = Brick.Size .Left = brickWidth .Top = 0 .Image = Brick.Image .SizeMode = PictureBoxSizeMode.StretchImage .BackColor = Color.Black End With Return myBrickn End Function Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load For i = -75 To Me.Width ' 重新调整数组长度,保留已有元素 ReDim Preserve Brickn(NoOfBrick) Brickn(NoOfBrick) = CreateBrick() Me.Controls.Add(Brickn(NoOfBrick)) brickWidth += 170 i += 170 NoOfBrick +=1 Next End Sub
方式2:使用List(Of PictureBox)(更推荐)
数组长度固定,动态添加元素效率低,List(Of T)支持动态扩容,无需手动调整长度:
Dim brickWidth As Integer = 0 ' 直接初始化空的PictureBox列表 Dim Brickn As New List(Of PictureBox) Public Function CreateBrick() As PictureBox Dim myBrickn As New PictureBox With myBrickn .Size = Brick.Size .Left = brickWidth .Top = 0 .Image = Brick.Image .SizeMode = PictureBoxSizeMode.StretchImage .BackColor = Color.Black End With Return myBrickn End Function Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load For i = -75 To Me.Width Dim newBrick = CreateBrick() Brickn.Add(newBrick) ' 直接添加到列表 Me.Controls.Add(newBrick) brickWidth += 170 i += 170 Next End Sub
修正碰撞检测的逻辑问题
你原有的Boll_control_Tick代码存在索引越界风险:NoOfBrick是数组/列表的总数量,而控件索引从0开始,直接用brickn(NoOfBrick)会访问不存在的元素。正确做法是遍历所有砖块检测碰撞:
针对数组的碰撞检测:
Private Sub Boll_control_Tick(sender As Object, e As EventArgs) Handles Boll_control.Tick ' 倒序遍历,避免移除元素时索引混乱 For i = NoOfBrick - 1 To 0 Step -1 If Ball.Bounds.IntersectsWith(Brickn(i).Bounds) Then Me.Controls.Remove(Brickn(i)) ' 调整数组长度并更新计数 ReDim Preserve Brickn(NoOfBrick - 2) NoOfBrick -= 1 Exit For ' 单次碰撞仅处理一个砖块,可按需调整 End If Next End Sub
针对List的碰撞检测(更简洁):
Private Sub Boll_control_Tick(sender As Object, e As EventArgs) Handles Boll_control.Tick ' 倒序遍历List,避免移除元素时遍历异常 For i = Brickn.Count - 1 To 0 Step -1 Dim brick = Brickn(i) If Ball.Bounds.IntersectsWith(brick.Bounds) Then Me.Controls.Remove(brick) Brickn.RemoveAt(i) ' 直接从List移除元素 Exit For End If Next End Sub
内容的提问来源于stack exchange,提问作者Mr. kismat
相关产品推荐
相关产品推荐

