Timer doesn't work

Hello,

I’m new to xojo and I’m 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 don’t think it’s the best way forward.
What I’m trying to do is to have e.g. 3 boxes. In array I’d like to have a sequence of values between 1 - 3. I’d like to read these values and if 1 than change colour of the box 1 let’s say for 1 second and then change it back to it’s 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.

Can anyone help please? Thanks a lot.

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?

The more detail you provide, the better.

@Kem Tekinay Thank you for your response!

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.

Thanks a lot for your help.

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.

Oops, wrong code formating:

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.

Awesome. Thanks a lot guys. I’ll try to implement your suggestions and will let you know if I was successful or not :slight_smile: