Changing Timer Frequency within it's own action event

I’m not sure if this is possible, or perhaps there is another way to achieve what I need?
I haven’t tested yet because I don’t want to muck up my code which is working to a ‘satisfactory’ point.

I have a simple xy graph displayed in a canvas. The user can pan/scroll left to right using the standard arrow keys at 1 pixel increments. When the Control key is pressed, the increments change to 20 pixels which accelerates the movement.

Here’s the code, in the timer action event - that’s scanning the keyboard:

[code] dim scrollIncrement as Integer
scrollIncrement = 1 //temp value

‘----------’
If Keyboard.AsyncControlKey then
scrollIncrement=20
else
scrollIncrement=1
End If

‘----------’
If Keyboard.AsyncKeyDown(&h7B) then //LeftArrow
ClearGraph
scrollX = scrollX + (-scrollIncrement)
DrawGraph
End If

‘----------’
If Keyboard.AsyncKeyDown(&h7C) then //RightArrow
ClearGraph
scrollX = scrollX + (scrollIncrement)
DrawGraph
end if
[/code]

The Timer is set to 25ms. This works nicely except for when the increment is set to 1 pixel, It’s very hard to stop the scroll of the image. The best way to describe this phenomenon is using a text editing program analogy. When you press a key (lets’s say ‘x’) then you only want one ‘x’. Holding the key down for a perhaps 1 second period results in a multitude of “x’s”. Sometimes this is required, otherwise we are left with a scenario where one has to tap the key very quickly just to get one event. I’ve seen this before with other software programs. Not acceptable with mine.

Hope this makes sense. I’ve fiddled around with the timer frequency to try and come up with a “happy medium” but it’s not good enough.

So I’m thinking that within the timer action event, I include a counter that counts an appropriate amount of times, then changes it’s own frequency setting? If I can do that, then I think I can come up with a solution.

I’m happy to hear any other ideas of going about this.

Yes, you can change the period from within the Action event handler of a timer. It does not break anything :wink:

You can do that for instance if you want the action to take place immediately, then later on. Start with a 1ms period single, and in the first occurrence, set for instance to 1000 and multiple.

Thanks Michel, that’s great to know. Now the hard part will be to implement it correctly - but doable now.

From what I’ve read 15ms is the limit of timer frequency using Windows. But not an issue in this regard.

I’ll post another question regarding sequential “If, Then, End If” statements vs “Case Select” which will is also a crucial issue to be determined.

Cheers.

[quote=295368:@Michel Bujardet]Yes, you can change the period from within the Action event handler of a timer. It does not break anything :wink:

You can do that for instance if you want the action to take place immediately, then later on. Start with a 1ms period single, and in the first occurrence, set for instance to 1000 and multiple.[/quote]

Do you know Michel if this change will trigger a Reset/Restart of the timer?

Sascha, from my understanding when the timer is enabled it will do the set time, then process the code in the action event. One would think that the initial timer value would be upheld, then the new value implemented afterwards regardless of whether the value was reset. Although I don’t really know yet.

I was concerned that re-setting the timer within it’s own action would cause a diminishing or exponential loop situation where some sort of catastrophe would occur.

My initial thoughts and reasoning (Algorithm) suggested it should work, but then I lost grasp of the idea, hence the question was asked.

I’ve got a 4 day break :slight_smile: so I intend to resolve the issue.

No, it does not, at least on Mac.

I vaguely remember reading something about Windows being different, but could not put my hands on that.

Well I hope it doesn’t trigger an immediate reset/restart, otherwise my whole concept is flawed and I will need to come up with a different solution.

Approaching Midnight here, so time to go to bed, get up have a good strong espresso or two and work on testing this. Sometimes trial and error combined with empirical evidence is the only way to fly.

don’t forget to factor in the time it take your routine to execute, and the framerate
60 frames per second is 16ms, the human eye can really only percieve 24-30fps
So I would say if you timer is less than 32ms+execution time, than you are not going to get bets results
if you are using canvas.invalidate (which you should be), then the app will update the screen as best it can.
You can call Invalidate 1000’s of times per second, but it may only execute a few times depending on resources.

Point being, just because you tell it to update every 15ms, doesn’t mean that it will

OK, quick try on Windows. Changing the period is no issue. Changing the mode from Single to Multiple does set the timer mode to Off, so you would have to instruct it again to do modeMultiple.

if me.Mode = Timer.ModeSingle then me.Mode = Timer.ModeOff me.Mode = Timer.ModeMultiple end if

In a recent thread Eugene Dakin was wondering how to do faster than the regular Windows timer. I suggested invalidate in the Paint event of a Canvas. The cycle takes just a couple milliseconds.

So there are ways to be MUCH faster than using a timer. Then the code has to be optimized in regards.

Thank you Michel :slight_smile:

Sounds like a bug, or?

Not sure it is a bug. It could be a specificity of the Windows control.

I just verified again on Mac to make sure, there changing mode does not reset the timer.

Don’t know about Xojo.Core.Timer yet.

[quote=295394:@Michel Bujardet]Not sure it is a bug. It could be a specificity of the Windows control.

I just verified again on Mac to make sure, there changing mode does not reset the timer.

Don’t know about Xojo.Core.Timer yet.[/quote]

I whish i would be at home right now to perform my own tests and i am very thankfull for you do this this on our behalf. :slight_smile:

Michel… my point was if your code takes 20ms to execute, and you have a timer period of 15ms, you won’t get 15ms resolution
at best it will be 20ms

[quote=295396:@Dave S]Michel… my point was if your code takes 20ms to execute, and you have a timer period of 15ms, you won’t get 15ms resolution
at best it will be 20ms[/quote]

Indeed. That is the reason why I insisted on optimization. That said, even very complex drawing in Paint seldom exceed 5 ms.

Just did the test with the same project. Xojo.Core.Timer mode can be switched on the fly on Windows without having to restart. Just like on Mac.

Thanks for testing this out Michel, and also thanks for everyone else’s input.

At the moment 20ms is fine - there is nothing in the paint event that will ever take that long to draw. Apart from re-setting the timer frequency, I did some other tests and came to the conclusion that my original requirement wasn’t going to work:

So after some investigation, I abandoned the timer and simply moved the code into the canvas KeyDown event. The OS takes care of it already :). Timers aren’t always the solution.

As usual, I’ve over-complicated things. However, I am interested in the implementation of Xojo.Core.Timer because there is a part of my Software that I’d like to re-draw the graph in ‘real time’ which would require 10ms (100 samples per second) or even as fines as 1ms if possible.

Currently I’m having issues with programmatically scaling my graph. Which has nothing to do with timers, but from what I can gather, to do with converting doubles to integer to display in pixels on the canvas.

I’ll start a new thread.

Complexity is a hard drug for programmers. The cure is minimalism :slight_smile:

Yes! agreed Michel. That “minimisation”, IS the “key” to effective software solutions.

There are tools like Xojo (and others), which I am very grateful for being able to use. I like to think I’m not the “wheel maker” but the person who says “Hey, I’ve got an idea - Let’s put four of these wheel things together, and call it a Cart”

Although of course, when there are issues with the cart, the wheel maker will always need to be consulted.