I figured I'd ask this here before I go back to other sites.
I'm trying to dynamically create a set of stopwatches and buttons. Each stopwatch will be controlled by a button which is also dynamically created.
However, each time I code it, I always ended wiring both buttons to control the same timer.
Can anyone help?
sorry but i cant get your point , can you please tell me that you want to create buttons and stopwatches dynamically , but how to get the number of buttons and stopwatches you have to create ? . sorry for my bad english , but rephrase your question so that i can help you
For indexCounter As Integer = 1 To TotalParticipants Step 1
participantClock = New Label
participantClock.Size = New Size(100, 20)
participantClock.Name = "participantClock" & indexCounter
participantClock.Location = New Point(139, (5 + ((indexCounter - 1) * 26)))
participantClock.BorderStyle = BorderStyle.Fixed3D
participantClock.TextAlign = ContentAlignment.MiddleRight
CenterPanel.Controls.Add(participantClock)
participantStop = New Button
participantStop.Size = New Size(58, 20)
participantStop.Location = New Point(245, (5 + ((indexCounter - 1) * 26)))
participantStop.BackColor = Color.Red
participantStop.ForeColor = Color.White
participantStop.Font = New Font(participantStop.Font, FontStyle.Bold)
participantStop.Text = "Stop"
CenterPanel.Controls.Add(participantStop)
participantTimer = New Timer
participantTimer.Start()
participantTimer.Enabled = True
participantTimer.Interval = 1
participantStopwatch = New Stopwatch
participantStopwatch.Start()
Next
The too long;didn't read version.
Essentially I'm creating a timer, label, stopwatch.
The label will display the stopwatch's elapsed result. But everytime I try to do this, I create a lot of buttons but only one label is updated and all of the buttons control that same (one) timer.
So far I was given the following to add on to the loop:
participantTimer.Tag = participantStopwatch
participantStopwatch.Tag = participantClock
AddHandler participantTimer.Tick, AddressOf Timer_Tick
But Stopwatches cannot have a Tag component according to VB.
Private Sub Timer_Tick(sender As Object, args As EventArgs)
Dim myTimer as Timer
Dim myStopwatch as Stopwatch
Dim myLabel as Label
' Cast to get the Timer object
If Not typeof sender Is Timer Then Exit Sub
myTimer = DirectCast(sender, Timer)
' Cast to get the Stopwatch object
If Not typeof myTimer.Tag Is Stopwatch Then Exit Sub
myStopwatch = DirectCast(myTimer.Tag, Stopwatch)
' Cast to get the Label object.
If Not typeof myStopwatch.Tag is Label Then Exit Sub
myLabel = DirectCast(myStopwatch.Tag, Label)
' Now we can finally update the correct Label from the Stopwatch.
myLabel.Text = myStopwatch.Value
End Sub>>But Stopwatches cannot have a Tag component according to VB.
Why not create a Array that stores something similar to a .Tag for the StopWatches and ReDim the Array each time you create them?
>>But Stopwatches cannot have a Tag component according to VB. Why not create a Array that stores something similar to a .Tag for the StopWatches and ReDim the Array each time you create them?
Can you let me see the code or psuedo code so I can guess at how to start on this?
I had a chance to play w/this "stopwatch" thread and got this.
Public Class Form1
Private lParticipantClock As Label, btnParticipantStop As Button, tmrParticipantTimer As Timer
Private iTotalParticipants As Integer
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
iTotalParticipants = 5
createStopWatches(iTotalParticipants)
End Sub
Private Sub createStopWatches(ByVal TotalParticipants As Integer)
For indexCounter As Integer = 1 To TotalParticipants Step 1
lParticipantClock = New Label : With lParticipantClock
.Name = "participantClock" & indexCounter
.Size = New Size(100, 20) : .Location = New Point(139, (5 + ((indexCounter - 1) * 26)))
.BorderStyle = BorderStyle.Fixed3D : .TextAlign = ContentAlignment.MiddleRight
End With : CenterPanel.Controls.Add(lParticipantClock)
btnParticipantStop = New Button : With btnParticipantStop
.Name = "ParticipantStop" & indexCounter
.Size = New Size(58, 20) : .Location = New Point(245, (5 + ((indexCounter - 1) * 26))) : .Cursor = Cursors.Hand
.BackColor = Color.Red : .ForeColor = Color.White : .Font = New Font(.Font, FontStyle.Bold) : .Text = "Stop"
AddHandler .Click, AddressOf _ParticipantButtons_Click
End With : CenterPanel.Controls.Add(btnParticipantStop)
tmrParticipantTimer = New Timer : With tmrParticipantTimer
AddHandler .Tick, AddressOf _ParticipantTimers_Tick
.Interval = 1 : .Start()
End With
Next
End Sub
Private Sub _ParticipantButtons_Click(sender As System.Object, e As System.EventArgs)
CType(sender, Button).Text = "done"
End Sub
Private Sub _ParticipantTimers_Tick(sender As System.Object, e As System.EventArgs)
Static iCounter As Integer = -1
iCounter += 1
For i As Integer = 1 To iTotalParticipants
If Not CType(CenterPanel.Controls("ParticipantStop" & i.ToString), Button).Text = "done" Then
CType(CenterPanel.Controls("participantClock" & i.ToString), Label).Text = iCounter.ToString("00:00:00")
End If
Next
End Sub
End Class Could Not use StopWatch.Value for some odd reason.
Regarding your recent post, see if this helps.
Public Class Form1
Private iTotalParticipants As Integer
Private arTags() As Boolean
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
createStopWatches(5)
End Sub
Private Sub createStopWatches(ByVal TotalParticipants As Integer)
ReDim arTags(TotalParticipants)
For indexCounter As Integer = 1 To TotalParticipants Step 1
arTags(indexCounter) = True '// set to true if needed.
'// all other code here to add.Controls.
Next
'// FOR.TESTING
arTags(1) = False
MsgBox(arTags(1))
End Sub
End Class
]edit[ Note: If using my previously posted code, you probably do not have to create a Timer for each participant, just use a single Timer to run the For/Next loop within it's .Tick event.
Could Not use StopWatch.Value for some odd reason.
It's because Stopwatches don't return .Values but rather TimeSpans. To get the value you'd have to use something like this:
Private Sub TotalTimer_Tick(sender As System.Object, e As System.EventArgs) Handles TotalTimer.Tick
Dim elapsed As TimeSpan = Me.matchStopwatch.Elapsed
MatchClockLbl.Text = String.Format("{0:00}:{1:00}:{2:00}.{3:0}", _
Math.Floor(elapsed.TotalHours), _
elapsed.Minutes, _
elapsed.Seconds, _
Math.Floor((elapsed.Milliseconds / 100)))
End Sub
EDIT: WOW. I just ran your code posted up in the forum post before this one. THANK YOU SIR! This is exactly what I was going for. Would you mind telling me what exactly the lines of code do, I haven't seen that kind of syntax before.
Okay. Now here's the last thing that I need to do.
There is one additional button that will exist on the form.
The button will add one additional row of timers to the form. So far I managed to manipulate the code given to me to actually add the row, but the timer is still continuing off the last added timer.
How can I reset that timer to 0 and add it to the form.
After this I think the program will be done. (Save for exporting all the times.)
EDIT: And evidently I now have the same problem I originally had... Whenever I add a row, it stops the last one and continues the timer on the following row. :/
Post your current.code, I'll see what I can do from there.
[edit]
>>Would you mind telling me what exactly the lines of code do, I haven't seen that kind of syntax before.
If not same code as mine previously posted, I'll comment the previously posted one, otherwise I'll comment your current.code.:)
+= glad I could help.
Here you go, I'll post up the full program code as I have it.:
Public Class MainFrm
Public TotalParticipants As Integer ' The total number of participants, will be set via an options form.
Private participantLbl As Label ' A label which will hold the ordered number.
Private participantName As TextBox ' A blank textbox to allow the user to name the participant
Private participantClock As Label ' This is a label which will display the stopwatch
Private btnParticipantStop As Button ' A button used to the stop the timer on the participant.
Private participantContinue As Button ' A button used to continue the timer when accidentally stopped.
Private participantTimer As Timer ' A timer to continuously update the labels on pulses.
' The options
Public numEntrants As Integer = 30 ' The maximum number of participants, set at 30 by default.
Public startingEntrants As Integer = 2 ' The number of timers to start simultaneously., set a 2 by default
Public entryTimer As Integer = 90 ' The timer to seperate and space the entries. Set to 90 by default
Public addAuto As Boolean = False ' A checkbox to determine whether or not to automatically add a participant.
Dim counterTimer As Integer ' A simple holder to count down the entryTimer.
Private participantStopwatch As New Stopwatch
Private matchStopwatch As New Stopwatch
Private Sub AboutToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles AboutToolStripMenuItem.Click
About.ShowDialog(Me)
End Sub
Private Sub ExitToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles ExitToolStripMenuItem.Click
If MessageBox.Show("All current data will be lost! Are you sure?", "Exit", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) = Windows.Forms.DialogResult.OK Then
Me.Close()
End If
End Sub
Private Sub AddPlayerBtn_Click(sender As System.Object, e As System.EventArgs) Handles AddPlayerBtn.Click
' Adjust our counter.
TotalParticipants += 1
TotalParicipantLbl.Text = TotalParticipants
If TotalParticipants = numEntrants Then
AddPlayerBtn.Visible = False
NoMoreEntrantsLbl.Visible = True
EndButton.Visible = True
CountDown.Enabled = False
CountDown.Stop()
EntrantDueClock.Text = ":" & String.Format("{0:00}", 0)
End If
End Sub
Private Sub StartButton_Click(sender As System.Object, e As System.EventArgs) Handles StartButton.Click
' The Start Match Button was clicked, hide Start Button and turn it into End Match
' Also, hide the warning, show the add player button, show the total counters.
StartButton.Visible = False
WarningLbl.Visible = False
AddPlayerBtn.Visible = True
EnteredLbl.Visible = True
TotalParicipantLbl.Visible = True
MaxLabel.Visible = True
MaxNumberLbl.Visible = True
' Set the Countdown Timer to be Equal to the Max Counter.
counterTimer = entryTimer
EntrantDueClock.Text = ":" & String.Format("{00}", counterTimer)
CountDown.Start()
'Disable the options windows
OptionsScreen.NumEntrants.Enabled = False
OptionsScreen.StartingNo.Enabled = False
OptionsScreen.EntryTimer.Enabled = False
' Add x number of rows to the sheet, where x equals the number given in StartingNo
TotalParticipants = startingEntrants
' Set our labels on the form
MaxNumberLbl.Text = numEntrants
TotalParicipantLbl.Text = TotalParticipants
' Continue to Do this until We hit our target
' Create the row (label, textfield, box) and start all timers (Countdown, Match Timer, Participant Timer)
createInitialStopWatches(TotalParticipants)
' Start the Match Timer (a count up timer)
TotalTimer.Enabled = True
TotalTimer.Start()
matchStopwatch.Start()
participantStopwatch.Start()
End Sub
Private Sub EndButton_Click(sender As System.Object, e As System.EventArgs) Handles EndButton.Click
' The Stop Event button will stop all active timers. (It's the end of the match.)
TotalTimer.Enabled = False
EndButton.Visible = False
TotalTimer.Stop()
matchStopwatch.Stop()
participantStopwatch.Stop()
End Sub
Private Sub OptionsToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles OptionsToolStripMenuItem.Click
OptionsScreen.ShowDialog(Me)
End Sub
Private Sub ReadMeToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles ReadMeToolStripMenuItem.Click
' Call the Read Me File
End Sub
Private Sub TotalTimer_Tick(sender As System.Object, e As System.EventArgs) Handles TotalTimer.Tick
Dim elapsed As TimeSpan = Me.matchStopwatch.Elapsed
MatchClockLbl.Text = String.Format("{0:00}:{1:00}:{2:00}.{3:0}", _
Math.Floor(elapsed.TotalHours), _
elapsed.Minutes, _
elapsed.Seconds, _
Math.Floor((elapsed.Milliseconds / 100)))
End Sub
Private Sub CountDown_Tick(sender As System.Object, e As System.EventArgs) Handles CountDown.Tick
counterTimer -= 1
If counterTimer = -1 Then
EntrantDueClock.Text = ":" & String.Format("{0:00}", 0)
ElseIf counterTimer = -2 Then
EntrantDueClock.Text = ":" & String.Format("{0:00}", 0)
If addAuto = True And TotalParticipants <> numEntrants Then
' The timer has expired, auto add is enabled, and there is still someone to enter... Add a new entrant.
TotalParticipants += 1
TotalParicipantLbl.Text = TotalParticipants
counterTimer = entryTimer
ElseIf addAuto = False Then
CountDown.Enabled = False
CountDown.Stop()
ResetTmrBtn.Visible = True
End If
Else
EntrantDueClock.Text = ":" & String.Format("{0:00}", counterTimer)
End If
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles ResetTmrBtn.Click
counterTimer = entryTimer
EntrantDueClock.Text = ":" & String.Format("{0:00}", counterTimer)
ResetTmrBtn.Visible = False
CountDown.Enabled = True
CountDown.Start()
End Sub
Private Sub createInitialStopWatches(ByVal StartingParticipants As Integer)
For indexCounter As Integer = 1 To StartingParticipants Step 1
participantClock = New Label : With participantClock
.Name = "participantClock" & indexCounter
.Size = New Size(100, 20) : .Location = New Point(139, (5 + ((indexCounter - 1) * 26)))
.BorderStyle = BorderStyle.Fixed3D : .TextAlign = ContentAlignment.MiddleRight
End With : CenterPanel.Controls.Add(participantClock)
btnParticipantStop = New Button : With btnParticipantStop
.Name = "ParticipantStop" & indexCounter
.Size = New Size(58, 20) : .Location = New Point(245, (5 + ((indexCounter - 1) * 26))) : .Cursor = Cursors.Hand
.BackColor = Color.Red : .ForeColor = Color.White : .Font = New Font(.Font, FontStyle.Bold) : .Text = "Stop"
AddHandler .Click, AddressOf _ParticipantButtons_Click
End With : CenterPanel.Controls.Add(btnParticipantStop)
participantTimer = New Timer : With participantTimer
AddHandler .Tick, AddressOf _ParticipantTimers_Tick
.Interval = 1 : .Start()
End With
Next
End Sub
Private Sub _ParticipantButtons_Click(sender As System.Object, e As System.EventArgs)
CType(sender, Button).Text = "done"
End Sub
Private Sub _ParticipantTimers_Tick(sender As System.Object, e As System.EventArgs)
Static iCounter As Integer = -1
iCounter += 1
For i As Integer = 1 To startingEntrants
If Not CType(CenterPanel.Controls("ParticipantStop" & i.ToString), Button).Text = "done" Then
CType(CenterPanel.Controls("participantClock" & i.ToString), Label).Text = iCounter.ToString("00:00:00")
End If
Next
End Sub
End Class
Essentially what's supposed to happen is this:
StartButton when clicked will call the function to make the initial timers and run the initial timers. It will also enable the "Add Partcipant" to view.
AddParticipant will add one additional row and start the timer for that one. While also making sure that you haven't hit the maximum. If the maximum is reached, disable Add Participant and enable the stop match button
When the total participants = numEntrants, A stop button will be enabled. The stop button will stop any and ALL timers. Both the participants (the dynamically created ones) AND the total match timer which is currently running.
If anything I can provide the entire solution in a Zip if you'd like. Just PM me your email address.
q.q.(quick.question)
If 2.participants running time of "00:23:45" and you add a new.participant, should the new.participant start w/"00:00:00", or should they start w/"00:23:45"
Disregard my previous post If this takes care of the issue.
Public Class Form1
Private lClock As Label, btnStop As Button, sw() As Stopwatch
Private iTotalParticipants As Integer '// keep count of players.
Private sButtonName As String = "Stop", sLabelName As String = "Clock", sButtonDone As String = "Done"
Private pnMain As Panel
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
pnMain = Panel1 '// Take control of Panel.
With Button1 : .Text = ".new" : .Cursor = Cursors.Hand : End With
With Button2 : .Text = ".add" : .Cursor = Cursors.Hand : End With
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
pnMain.Controls.Clear() '// clear.Panel.
iTotalParticipants = 0 '// reset players.
createInitialStopWatches(2) '// start w/2 players.
End Sub
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
createInitialStopWatches(1) '// a single player.
End Sub
#Region "-----===-----===-----===-----===-----=== DYNAMIC.CONTROLS ===-----===-----===-----===-----===-----"
Private Sub createInitialStopWatches(ByVal numberOfParticipantsToAdd As Integer)
For i As Integer = 1 To numberOfParticipantsToAdd
iTotalParticipants += 1 '// increase players total.
addStopWatchControls(iTotalParticipants) '// add new.player's controls.
Next
End Sub
Private Sub addStopWatchControls(ByVal selCtlIndex As Integer)
ReDim Preserve sw(iTotalParticipants) '// Redim the StopWatch.Array and keep previous stopWatches.
sw(selCtlIndex) = New Stopwatch '// new stopWatch for new participant.
sw(selCtlIndex).Start()
lClock = New Label : With lClock
.Name = sLabelName & selCtlIndex
.Size = New Size(100, 20) : .Location = New Point(139, (5 + ((selCtlIndex - 1) * 26)))
.BorderStyle = BorderStyle.Fixed3D : .TextAlign = ContentAlignment.MiddleRight
End With : pnMain.Controls.Add(lClock) '// add.Label.
btnStop = New Button : With btnStop
.Name = sButtonName & selCtlIndex
.Size = New Size(58, 20) : .Location = New Point(245, (5 + ((selCtlIndex - 1) * 26))) : .Cursor = Cursors.Hand
.BackColor = Color.Red : .ForeColor = Color.White : .Font = New Font(.Font, FontStyle.Bold) : .Text = sButtonName
AddHandler .Click, AddressOf _ParticipantStopButtons_Click '// give the Button an event to handle.
End With : pnMain.Controls.Add(btnStop) '// add.Button.
End Sub
Private Sub _ParticipantStopButtons_Click(sender As System.Object, e As System.EventArgs)
CType(sender, Button).Text = sButtonDone '// get sender and set .Text.
End Sub
#End Region
Private WithEvents tmrMain As New Timer With {.Enabled = True} : Private tsTemp As New TimeSpan
Private Sub _tmrMain_Tick(sender As System.Object, e As System.EventArgs) Handles tmrMain.Tick
If Not iTotalParticipants = 0 Then
For i As Integer = 1 To iTotalParticipants
If Not sw.Length = 0 Then
If Not CType(pnMain.Controls(sButtonName & i.ToString), Button).Text = sButtonDone Then '// check for btn.Text.
tsTemp = sw(i).Elapsed : With tsTemp '// set TimeSpan for StopWatch.
CType(pnMain.Controls(sLabelName & i.ToString), Label).Text = String.Format("{0:00}:{1:00}:{2:00}.{3:0}", _
Math.Floor(.TotalHours), .Minutes, .Seconds, Math.Floor((.Milliseconds / 100))) '// display result.
End With
End If
End If
Next
End If
End Sub
End Classq.q.(quick.question) If 2.participants running time of "00:23:45" and you add a new.participant, should the new.participant start w/"00:00:00", or should they start w/"00:23:45"
The new entrants will have a timer of 00:00:00 and count up from there, the button that is generated with add on will control only the timer to its left.