0

I have a panel with 50 button and 1 label in my form

Private Sub flp_table_paint(sender As Object, e As PaintEventArgs) Handles flp_table.Paint

        Dim i As Integer
        For i = 1 To 50
            Dim btn_tableNo As New Button
            btn_tableNo.Width = 40
            btn_tableNo.Height = 40
            btn_tableNo.Text = i
            AddHandler btn_tableNo.Click, AddressOf TableButtonClicked

            Dim timer As New Timer
            timer.Tag = i

            Me.flp_table.Controls.Add(btn_tableNo)
        Next

End Sub

What I try to do is, for every single button that i clicked they will start their own timer and show on the label.

Example:

11:00:00PM - Clicked on Button1 , lb_timer will show 1,2,3,4...

11:00:30PM - Clicked on Button2 , lb_timer will show 1,2,3,4...

11:00:45PM - Clicked on Button1 again, lb_timer will show 45,46,47,48...

11:00:50PM - Clicked on Button2 again, lb_timer will show 20,21,22,23...

Here is what i try so far, but fail...

Private Sub TableButtonClicked(ByVal sender As Object, ByVal e As EventArgs)
    Dim currButton As Button = sender
    selectedTable = currButton

    For Each timer As Timer In Me.Controls
        If timer.Tag = selectedTable.Text Then
            timer.Start()
            lb_timer.Text = timer.ToString
        End If
    Next
End Sub

I have no idea how to make it work, please help me...

1
  • You shouldn't be doing anything in a paint event except paint something. That's also a dangerous timer because you didn't declare it at the form scope, so the garbage collector doesn't know how to clean that up. You also don't do anything with the timer — it's certainly not a part of the Controls collection you are looping through later. Timers are not controls, they are components. Commented Dec 2, 2016 at 17:49

2 Answers 2

1

Here asynchronous approach without Timer and one eventhandler for all buttons

' In constructor
AddHandler button1.Click, AddressOf Button_Click
AddHandler button2.Click, AddressOf Button_Click
AddHandler button3.Click, AddressOf Button_Click
' ... rest of buttons


' variable will keep name of the button which number is showing
Private _selectedButtonName As String

Private Async Sub Button_Click(sender As object, e As EventArgs)
    Dim button As Button = DirectCast(sender, Button)
    _selectedButtonName = button.Name

    Dim isRunning As Boolean = (button.Tag IsNot Nothing)
    If isRunning = True Then return

    await StartCounterAsync(button)
End Sub

Private Async Function StartCounterAsync(Button button) As Task
    button.Tag = new object()
    Dim number As Integer = 0
    While True
        await Task.Delay(1000)
        number += 1

        If _selectedButtonName.Equals(button.Name)
            lb_timer.Text = $"{button.Name}: {number}"
        End If
    End While
End Function

You can add CancellationToken in case you want reset counters.

Sign up to request clarification or add additional context in comments.

Comments

0

Sadly the timer doesn't show elapsed time. An easier control to use for your purpose would be the StopWatch control. Its quite similar and will show a running time.

Dim StopWatchTest As New Stopwatch
StopWatchTest.Start()
Dim EllapsedTime As String = StopWatchTest.ElapsedMilliseconds / 1000

However since you want to continually update the label with the ellapsed time, you would need a timer to update the label at every tick.

Dim UpdateLabelTimer As New Timer()
UpdateLabelTimer.Interval = 1000 'How often to update your label (in milliseconds)
AddHandler UpdateLabelTimer.Tick, AddressOf Tick
UpdateLabelTimer.Start()

----------

Private Sub Tick()
    lblLabel.text = StopWatchTest.ElapsedMilliseconds
End Sub

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.