Harry Allen
Harry Allen

Reputation: 91

VB.NET | Array of pictureboxes in panel: Object reference not set to an instance of an object

In the code below I am attempting to change the tag of an existing control that was created in the array 'pictureboxes(9, 9)'. When I try to do this, I get the error 'Object reference not set to an instance of an object.'. This is done in the checkdata sub, near the bottom of the code with the comment 'Object reference not set to an instance of an object.'.

The string that is passed through to the sub is a long string of numbers, and the pictureboxes are placed into a layoutpanel if that is helpful.

I understand what this error means, I am aware that pictureboxes(i, j) is = nothing when breakpointed; I just don't know how to fix it :s

Any help is greatly appreciated and hopefully I will be quick to answer any comments/answers.

Thank you

Imports System.Net.Sockets
Imports System.Threading
Imports System.Text
Imports System.Net

Public Class Form1
'0 as default tile, 1 as clicked, 3 as set mine (host perspective)
Dim tiles() As Integer = {0}
Public pictureboxes(9, 9) As PictureBox
Dim flagged() As Integer
Dim clicked As Integer()
Dim columns As Integer = 10
Dim rows As Integer = 10
Dim placedMinesCount As Integer = 0
Dim formattedTag As String()
Public turn As Boolean = False
Dim stringToSend As String

Public Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    For i As Byte = 0 To 9
        For j As Byte = 0 To 9

            pictureboxes(i, j) = New PictureBox
            pictureboxes(i, j).Height = 60
            pictureboxes(i, j).Width = 60
            pictureboxes(i, j).ImageLocation = "0.png"
            pictureboxes(i, j).Tag = "0|" & i & ", " & j

            AddHandler pictureboxes(i, j).Click, AddressOf Tile_Click

            Dim column As Integer = j
            Dim row As Integer = i

            Panel.Controls.Add(pictureboxes(i, j), column, row)

        Next
    Next

    If Login.isHost = True Then
        Me.Text = "Set your mines (10)"
        turn = True
    ElseIf Login.isHost = False Then
        Me.Text = "Await your turn"
        btnEndTurn.Visible = False
        btnEndTurn.Enabled = False
    End If
End Sub

Protected Sub Tile_Click(ByVal sender As Object, ByVal e As EventArgs)
    formatSenderTag(sender.tag)
    If Login.isHost = True Then
        Dim clickAction As String = formattedTag(0)

        Select Case clickAction
            Case "0"
                If placedMinesCount < 10 Then
                    placedMinesCount = placedMinesCount + 1
                    sender.imagelocation = "3.png"
                    sender.tag = "3"
                    Me.Text = "Set your mines (" & 10 - placedMinesCount & ")"

                ElseIf placedMinesCount >= 10 Then
                    MsgBox("You have placed all of your 10 Mines")
                End If
            Case "2"
                MsgBox("You cannot set a mine here")
            Case "3"
                placedMinesCount = placedMinesCount - 1
                Me.Text = "Set your mines (" & 10 - placedMinesCount & ")"
                sender.imagelocation = "0.png"
                sender.tag = "0"
        End Select


    ElseIf Login.isHost = False Then
        Dim clickAction As String = formattedTag(0)
        Select Case clickAction
            Case "0"
                sender.tag = "1"
                sender.imagelocation = "1.png"
            Case "3"
                MsgBox("Game Over")
            Case "2"
                MsgBox("Already Clicked")
        End Select
    End If
End Sub

Private Sub formatSenderTag(ByVal sender As String)
    'split into array 
    'element 0 as TILE TYPE
    'element 1 as TILE LOCATION
    formattedTag = sender.Split(New String() {"|"}, StringSplitOptions.None)
End Sub

Private Sub Form_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
    End
End Sub

Private Sub btnEndTurn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEndTurn.Click
    turn = False

    gridtostring()
    senddata()
End Sub

Private Sub gridtostring()
    For i As Byte = 0 To 9
        For j As Byte = 0 To 9
            formatSenderTag(pictureboxes(i, j).Tag & "|")
            stringToSend = stringToSend & formattedTag(0)
        Next
    Next
End Sub

Private Sub senddata()
    '***SEND STUFF
    'Assuming you have a textbox with the data you want to send
    If (Not String.IsNullOrEmpty(stringToSend)) Then
        Dim data() As Byte = Encoding.ASCII.GetBytes(stringToSend)
        Login.sendingClient.Send(data, data.Length)
    End If
End Sub

Public Sub checkdata(ByVal data As String)
    If Not data = stringToSend Then
        'Dim loopcount As Integer = 0
        For i As Byte = 0 To 9
            For j As Byte = 0 To 9
                Dim loopcount As Integer = (i.ToString & j.ToString) + 1
                'Dim pineapple As String = pictureboxes(i, j).Tag
                'pictureboxes(i, j).Tag = GetChar(data, 3)

                pictureboxes(i, j).Tag = GetChar(data, loopcount) & "|" & i & ", " & j '***Object reference not set to an instance of an object.***
                formatSenderTag(pictureboxes(i, j).Tag)
                pictureboxes(i, j).ImageLocation = formattedTag(0)
                pictureboxes(i, j).ImageLocation = "0.png"
                'Panel.Controls(pictureboxes(i, j).Tag) = GetChar(data, 3) '.Tag = GetChar(data, 3)

            Next
        Next
    End If
End Sub
End Class

***AND BELOW IS THE OTHER FORM WHICH CALLS CHECKDATA()

Imports System.Net.Sockets
Imports System.Threading
Imports System.Text
Imports System.Net

Public Class Login

Dim Port As Integer = 8123
Private Const broadcastAddress As String = "255.255.255.255"
Public receivingClient As UdpClient
Public sendingClient As UdpClient
Dim sendAddress As String
Dim ServerMode As Boolean = False
Public isHost As Boolean = true
Dim returndata As String

Private Sub Login_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

End Sub

Private Sub ComboWANLAN_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ComboWANLAN.SelectedIndexChanged
    If ComboWANLAN.Text = "Online (WAN)" Then
        txtSendAddress.Enabled = True
    ElseIf ComboWANLAN.Text = "Offline (LAN)" Then
        txtSendAddress.Enabled = False
    End If
End Sub

Private Sub btnConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnect.Click
    '***START PORT LISTENING/SENDING AND NETWORKING STUFFS
    Port = txtPort.Text
    InitializeSender()
    InitializeReceiver()

End Sub

Private Sub btnHost_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnHost.Click
    '***START PORT LISTENING/SENDING AND NETWORKING STUFFS
    Port = txtPort.Text
    InitializeSender()
    InitializeReceiver()
    isHost = True
    Me.Hide()
    Form1.Show()
End Sub

Private Sub InitializeSender()
    If ComboWANLAN.Text = "Offline (LAN)" Then
        sendingClient = New UdpClient(broadcastAddress, Port)
        'Use broadcastAddress for sending data locally (on LAN), otherwise you'll need the public (or global) IP address of the machine that you want to send your data to
    ElseIf ComboWANLAN.Text = "Online (WAN)" Then
        sendAddress = txtSendAddress.Text
        sendingClient = New UdpClient(sendAddress, Port)
        'Use broadcastAddress for sending data locally (on LAN), otherwise you'll need the public (or global) IP address of the machine that you want to send your data to
    End If
    sendingClient.EnableBroadcast = True
End Sub

Private Sub InitializeReceiver()
    receivingClient = New UdpClient(Port)
    ThreadPool.QueueUserWorkItem(AddressOf Receiver) 'Start listener on another thread
End Sub

Private Sub Receiver()
    Dim endPoint As IPEndPoint = New IPEndPoint(IPAddress.Any, port) 'Listen for incoming data from any IP on the specified port
    Do While True 'Notice that i've setup an infinite loop to continually listen for incoming data
        Dim data() As Byte
        data = receivingClient.Receive(endPoint)
        If Form1.turn = False Then
            returndata = Encoding.ASCII.GetString(data) 'Recived data as string
            Form1.checkdata(returndata)
        End If
    Loop
End Sub

Private Sub Form_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
    End
End Sub
End Class

***STACK TRACE

   at Minesweeper.Form1.checkdata(String data) in                c:\users\harry\documents\visual studio     2010\Projects\Minesweeper\Minesweeper\Form1.vb:line 139
   at Minesweeper.Login.Receiver() in C:\Users\Harry\Documents\Visual Studio     2010\Projects\Minesweeper\Minesweeper\Login.vb:line 71
   at Minesweeper.Login._Lambda$__1(Object a0) in C:\Users\Harry\Documents\Visual Studio 2010\Projects\Minesweeper\Minesweeper\Login.vb:line 61
   at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
    at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

Note: Screwed up with the spacings in some places

Upvotes: 2

Views: 460

Answers (1)

ib11
ib11

Reputation: 2568

This code does not give an error with the data you gave:

checkdata("00000000000000000000000000000000000000000000000000000000000000000000000000000000‌​00000000000000000000")

Public Sub checkdata(ByVal data As String)
    If Not data = stringToSend Then
        'Dim loopcount As Integer = 0
        For i As Byte = 0 To 9
            For j As Byte = 0 To 9
                Dim loopcount As Integer = (i.ToString & j.ToString) + 1
                'Dim pineapple As String = pictureboxes(i, j).Tag
                'pictureboxes(i, j).Tag = GetChar(data, 3)

                pictureboxes(i, j).Tag = GetChar(data, loopcount) & "|" & i & ", " & j '***Object reference not set to an instance of an object.***
                formatSenderTag(pictureboxes(i, j).Tag)
                pictureboxes(i, j).ImageLocation = formattedTag(0)
                pictureboxes(i, j).ImageLocation = "0.png"
                'Panel.Controls(pictureboxes(i, j).Tag) = GetChar(data, 3) '.Tag = GetChar(data, 3)

            Next
        Next
    End If
End Sub

Looking at your stack trace and code, you are missing the instantiation of Form1 in your login class. I think this can be the problem.

Try adding this to the beginning of your Login class:

Dim Form1 as New Form1

Upvotes: 1

Related Questions