Im new to xojo and Im really struggling with something very simple.
I would like to delay a process. I managed to have it half working using thread.sleep but I dont think its the best way forward.
What Im trying to do is to have e.g. 3 boxes. In array Id like to have a sequence of values between 1 - 3. Id like to read these values and if 1 than change colour of the box 1 lets say for 1 second and then change it back to its original colour, then do the same for the second number stored in array and so on.
I tried to follow the documentation explain how to use timer but with no luck and no idea why.
Happy to help, but keep in mind that Timers work just fine for the majority of us, so it would help to know how you’re trying to implement your Timer. Did you put it on a Window? Did you fill its Action event with code and, if so, what code? Where and how are you trying to activate it?
Here is what I’m trying to do. When clicked button do this:
For Each cislo As Integer in cubeOrder()
If i=1 Then
Window1.Rectangle1.FillColor = &cc9dd69
//time delay e.g. 1 sec should be here
Window1.Rectangle1.FillColor = &c000000
ElseIf i=2
Window1.Rectangle2.FillColor = &c349823
//time delay e.g 1 sec should be here
Window1.Rectangle1.FillColor = &c000000
End If
Next
To be honest I’m not really sure how to implement the timer. I found somewhere this: App.SleepCurrentThread(500) but for some reason it works e.g. with sounds (play sound, delay, play another sound) but when I was trying to change the colour of the box it wouldn’t work. No idea why.
You have to think in terms of ‘events chaining’.For Each cislo As Integer in cubeOrder()
If i=1 Then
Window1.Rectangle1.FillColor = &cc9dd69
//time delay e.g. 1 sec should be here
//Window1.Rectangle1.FillColor = &c000000
// -> Here, trigger your Timer. In the Timer.Action event then set your Window1.Rectangle1.FillColor = &c000000
// You can create a property on your window where you store the Control to change (and perhaps the color you want).
ElseIf i=2
'...
Next
Cheers,
Guy.
For Each cislo As Integer in cubeOrder()
If i=1 Then
Window1.Rectangle1.FillColor = &cc9dd69
// -> Here, trigger your Timer. In the Timer.Action event then set your Window1.Rectangle1.FillColor = &c000000
// You can create a property on your window where you store the Control to change
// (and perhaps the color you want) so the Timer will know which one to change.
ElseIf i=2
// ...
End If
Next
In general, you should stop trying to insert a pause into linear code and embrace an event driven coding model. The old model is
1) Do Something
2) Wait a while
3) Do Something Else
The approach you want is
1) Do Something
2) Start a timer
2.5) Return - nothing more to do in this code block
Sometime later, the timer will go off and execute its Action event. In that event, you want
3) Do Something Else
Note that the 2 sections of code are completely separated from each other. That is actually a Good Thing. It may not seem like it at first, but there is much power here. There are several OOP Design Patterns that make this easier and more flexible. It would be worth the time to read up on design patterns.
As a simple approach, make CubeOrder() a property of the Window and add the properties CubeOrderIndex and whatever i holds too. Also add a property for the state of the Rectangle. Add a Timer to your window called something like FillRectTimer. Add an event, Action, to the Timer and put code in there that will start a method, DoFillRectTimerAction. That method will fill the rectangle based on CubeIndex, then advance CubeIndex, something like this:
if CubeOrderIndex <= CubeOrder.Ubound then
dim c as Color
if DoClearRect then
c = &c000000
else
select case i
case 1
c = & cc9dd69
case 2
c = & c349823
end select
end if
If i=1 Then
Window1.Rectangle1.FillColor = c
ElseIf i=2 then
Window1.Rectangle2.FillColor = c
end if
if DoClearRect then
CubeOrderIndex = CubeOrderIndex + 1
end if
DoClearRect = not DoClearRect
else
// We're done, so turn off the Timer
FillRectTimer.Mode = 0
end if
Now all your button has to do is set the properties and start the Timer. On each pass of the Timer, the Rectangle will either be filled or cleared, then it will pause until the next pass. If you want immediate action, call FillRectTimerAction directly so the first Rectangle will be filled.
As Tim mentioned, there are design patterns that would make this “cleaner”, and you should really look into Control Sets for your Rectangles, but this is a good starting point. The idea is to let the Timer do the work during idle time.