You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何访问动态添加的Label控件?解决System.NullReferenceException报错

VB.NET动态控件计时程序空引用异常解决方法

问题描述

我正在开发一款计时程序,已实现动态添加多个参赛项的功能,但在通过动态添加的Button激活计时器,将计时结果显示到对应动态添加的Label控件时遇到问题。点击按钮触发事件时,程序抛出错误:System.NullReferenceException: 'Object variable or With block variable not set.'

原代码如下:

Public Class Form1
ReadOnly MyForm
Dim ss, tt, vv As Integer
Dim ss1, tt1, vv1, ww1 As Integer

'Dim NewLab1


Dim CarNum

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim NewBut1 = New Button
    Dim NewBut2 = New Button
    Dim NewLab1 = New Label
    Dim NewLab2 = New Label
    Dim NewLab3 = New Label
    Timer3.Enabled = True




    ' NewBut1()

End Sub

Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    Label3.Text = Format(ss, "00:") & Format(tt, "00:") & Format(vv, "00")
    vv = vv + 1
    If vv > 59 Then
        vv = 0
        tt = tt + 1
    End If
    If tt = 2 Then
        vv = 0
        tt = 0
        Label3.Text = "00:00:00"
        Timer1.Enabled = False
        MessageBox.Show("time ended")
    End If
End Sub

Private Sub Timer3_Tick(sender As Object, e As EventArgs) Handles Timer3.Tick
    Label2.Text = Format(Now, "hh:mm:ss")
End Sub

Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    CarNum = InputBox("Add Car Number", "Car Number")

    Dim NewBut1 = New Button
    Dim NewBut2 = New Button
    Dim NewLab1 = New Label
    Dim NewLab2 = New Label
    Dim NewLab3 = New Label


    With NewBut1
        .BackColor = Color.Red
        .ForeColor = Color.White
        .Text = "Car " & CarNum & " Pit IN"
        .Location = New Point(12, 200)
        .Height = 60
        .Width = 188
        .Font = New Font("Arial Rounded ", 16, FontStyle.Bold)
        AddHandler NewBut1.Click, AddressOf NewBut1_Click
    End With
    With NewBut2
        .BackColor = Color.Lime
        .ForeColor = Color.Black
        .Text = "Car " & CarNum & " Pit OUT"
        .Location = New Point(225, 200)
        .Height = 60
        .Width = 188
        .Font = New Font("Arial Rounded", 16, FontStyle.Bold)



    End With
    With NewLab1
        .BackColor = Color.Black
        .ForeColor = Color.Lime
        .Location = New Point(537, 200)
        .Height = 60
        .Width = 188
        .Font = New Font("Arial Rounded", 16, FontStyle.Bold)
        .TextAlign = ContentAlignment.MiddleCenter
        .Text = "Pit Stop Timer"

    End With

    With NewLab2
        .BackColor = Color.Black
        .ForeColor = Color.Lime
        .Location = New Point(748, 200)
        .Height = 60
        .Width = 188
        .Font = New Font("Arial Rounded", 16, FontStyle.Bold)
        .TextAlign = ContentAlignment.MiddleCenter
        .Text = "Stint Timer"

    End With
    With NewLab3
        .BackColor = Color.Black
        .ForeColor = Color.Lime
        .Location = New Point(953, 200)
        .Height = 60
        .Width = 188
        .Font = New Font("Arial Rounded", 16, FontStyle.Bold)
        .TextAlign = ContentAlignment.MiddleCenter
        .Text = "Timer 3"

    End With



    Controls.Add(NewBut1)
    Controls.Add(NewBut2)
    Controls.Add(NewLab1)
    Controls.Add(NewLab2)
    Controls.Add(NewLab3)



End Sub

Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
    Dim NewLab1 As Label
    NewLab1.Text = Format(ss1, "00:") & Format(tt1, "00:") & Format(vv1, "00.") & Format(ww1, "00.")
    vv1 = vv1 + 1
    If vv1 > 59 Then
        vv1 = 0
        tt1 = tt1 + 1
    End If
    If tt1 = 2 Then
        vv1 = 0
        tt1 = 0
        Label1.Text = "00:00:00.00"
        Timer2.Enabled = False
        MessageBox.Show("time ended")
    End If
End Sub

Private Sub NewBut1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
    Timer2.enabled = True

End Sub


Private Sub Button21_Click(sender As Object, e As EventArgs) Handles Button21.Click
    Timer1.Enabled = True

End Sub
Sub newlab1()

End Sub
End Class

问题根源

  1. 空引用直接访问:Timer2_Tick事件里声明了Dim NewLab1 As Label但未初始化,直接调用NewLab1.Text触发空引用异常
  2. 局部变量无法跨方法访问:动态创建的NewLab1是Button2_Click里的局部变量,Timer2无法直接获取这个控件实例
  3. 控件重叠:所有动态添加的控件都使用相同的Y坐标,导致后续添加的控件会覆盖之前的,无法正常交互
  4. 全局计时器冲突:所有参赛项共用一个Timer2,多个车辆计时会互相干扰

解决方案

通过封装类管理每个参赛项的控件和计时数据,为每个车辆创建独立计时器,同时优化控件布局避免重叠:

Public Class Form1
    ' 封装每个参赛车辆的控件和计时数据
    Private Class CarTimerItem
        Public PitInButton As Button
        Public PitOutButton As Button
        Public PitStopLabel As Label
        Public StintLabel As Label
        Public Timer3Label As Label
        Public Timer As Timer
        Public ss1, tt1, vv1 As Integer ' 调整计时变量,用vv1做百分秒
    End Class

    Private carItems As New List(Of CarTimerItem)
    Private nextControlTop As Integer = 200 ' 下一个控件的起始Y坐标

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Timer3.Enabled = True
    End Sub

    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        Static ss, tt, vv As Integer
        Label3.Text = Format(ss, "00:") & Format(tt, "00:") & Format(vv, "00")
        vv += 1
        If vv > 59 Then
            vv = 0
            tt += 1
        End If
        If tt = 2 Then
            vv = 0
            tt = 0
            Label3.Text = "00:00:00"
            Timer1.Enabled = False
            MessageBox.Show("时间结束")
        End If
    End Sub

    Private Sub Timer3_Tick(sender As Object, e As EventArgs) Handles Timer3.Tick
        Label2.Text = Format(Now, "hh:mm:ss")
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        Dim carNum = InputBox("添加车辆编号", "车辆编号")
        If String.IsNullOrEmpty(carNum) Then Return

        Dim newItem As New CarTimerItem

        ' 创建Pit IN按钮
        newItem.PitInButton = New Button
        With newItem.PitInButton
            .BackColor = Color.Red
            .ForeColor = Color.White
            .Text = "车辆 " & carNum & " 进站"
            .Location = New Point(12, nextControlTop)
            .Height = 60
            .Width = 188
            .Font = New Font("Arial Rounded", 16, FontStyle.Bold)
            AddHandler .Click, Sub(s, args)
                                  newItem.Timer.Enabled = Not newItem.Timer.Enabled
                                  .Text = If(newItem.Timer.Enabled, "暂停计时", "车辆 " & carNum & " 进站")
                              End Sub
        End With

        ' 创建Pit OUT按钮
        newItem.PitOutButton = New Button
        With newItem.PitOutButton
            .BackColor = Color.Lime
            .ForeColor = Color.Black
            .Text = "车辆 " & carNum & " 出站"
            .Location = New Point(225, nextControlTop)
            .Height = 60
            .Width = 188
            .Font = New Font("Arial Rounded", 16, FontStyle.Bold)
            AddHandler .Click, Sub(s, args)
                                  newItem.Timer.Enabled = False
                                  newItem.ss1 = 0
                                  newItem.tt1 = 0
                                  newItem.vv1 = 0
                                  newItem.PitStopLabel.Text = "进站计时"
                              End Sub
        End With

        ' 创建进站计时标签
        newItem.PitStopLabel = New Label
        With newItem.PitStopLabel
            .BackColor = Color.Black
            .ForeColor = Color.Lime
            .Location = New Point(537, nextControlTop)
            .Height = 60
            .Width = 188
            .Font = New Font("Arial Rounded", 16, FontStyle.Bold)
            .TextAlign = ContentAlignment.MiddleCenter
            .Text = "进站计时"
        End With

        ' 创建阶段计时标签
        newItem.StintLabel = New Label
        With newItem.StintLabel
            .BackColor = Color.Black
            .ForeColor = Color.Lime
            .Location = New Point(748, nextControlTop)
            .Height = 60
            .Width = 188
            .Font = New Font("Arial Rounded", 16, FontStyle.Bold)
            .TextAlign = ContentAlignment.MiddleCenter
            .Text = "阶段计时"
        End With

        ' 创建第三个计时标签
        newItem.Timer3Label = New Label
        With newItem.Timer3Label
            .BackColor = Color.Black
            .ForeColor = Color.Lime
            .Location = New Point(953, nextControlTop)
            .Height = 60
            .Width = 188
            .Font = New Font("Arial Rounded", 16, FontStyle.Bold)
            .TextAlign = ContentAlignment.MiddleCenter
            .Text = "计时器3"
        End With

        ' 创建独立计时器
        newItem.Timer = New Timer
        newItem.Timer.Interval = 10 ' 10毫秒更新一次,提升计时精度
        AddHandler newItem.Timer.Tick, Sub(s, args)
                                           newItem.vv1 += 1
                                           If newItem.vv1 > 99 Then ' 百分秒逻辑
                                               newItem.vv1 = 0
                                               newItem.ss1 += 1
                                           End If
                                           If newItem.ss1 > 59 Then
                                               newItem.ss1 = 0
                                               newItem.tt1 += 1
                                           End If
                                           ' 更新对应车辆的进站计时标签
                                           newItem.PitStopLabel.Text = Format(newItem.tt1, "00:") & Format(newItem.ss1, "00:") & Format(newItem.vv1, "00")
                                       End Sub

        ' 添加控件到窗体
        Controls.Add(newItem.PitInButton)
        Controls.Add(newItem.PitOutButton)
        Controls.Add(newItem.PitStopLabel)
        Controls.Add(newItem.StintLabel)
        Controls.Add(newItem.Timer3Label)

        ' 保存到列表,方便后续管理
        carItems.Add(newItem)

        ' 下一组控件向下偏移,避免重叠
        nextControlTop += 70
    End Sub

    Private Sub Button21_Click(sender As Object, e As EventArgs) Handles Button21.Click
        Timer1.Enabled = True
    End Sub
End Class

关键修改点

  1. 封装独立数据:用CarTimerItem类把每个车辆的按钮、标签和计时变量绑定在一起,确保数据不冲突
  2. 独立计时器:为每个车辆创建专属Timer,避免全局计时器的干扰
  3. 控件布局优化:通过nextControlTop变量动态调整控件Y坐标,添加的控件不会重叠
  4. 直接关联事件:用Lambda表达式在创建按钮时直接绑定对应车辆的计时器操作,无需额外的全局事件处理
  5. 精度优化:调整计时逻辑为百分秒级,提升计时准确性

内容的提问来源于stack exchange,提问作者Dazza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 11:40:30