PDA

View Full Version : Slow down key repeat rate of QSpinBox/QDoubleSpinBox



SeanM
27th May 2014, 21:44
I've got a spinbox widget (QDoubleSpinBox) which is used to send a command over a serial port to a hardware device. The desired behavior was the valueChanged() signal was connected directly to the sendCommand() slot, but we're running into a problem with the hardware device not being able to keep up when the user uses the keyboard to change the value.

What we're noticing is that if the user holds down the mouse button on one of the GUI controls, the spinbox increments at a certain rate - a rate that the serial port and device can keep up with. But if the user uses the keyboard up/down keys to change the control and holds down the key, the rate the spinbox increments is MUCH faster than the mouse method. Unfortunately due to a bug in the hardware device it gets confused with all these commands coming that quickly, but we're not able to change the device firmware very easily.

So I'm looking for a way to slow down the valueChanged() signals when using a keyboard. The only thing I can find is that spinboxes have an "accelerated" property, but I've already verified that is set to false.

Is there anything else I can do? The only solution I can think of is instead of connecting the valueChanged() signal directly to my sendCommand() slot, I could put an intermediate slot with a timer in between, so the valueChanged() signal causes this intermediate slot to store the value and start a timer, if the timer expires, then the sendCommand() slot would get called, but otherwise the timer keeps getting reset and no command gets sent.

Am I missing another solution?

ChrisW67
27th May 2014, 23:24
The timer would have been my first option.

The keyboard repeat rate is set by the operating system so you don't have direct control over that. You might be able to install an event filter and only pass keypresses that are far enough apart in time.

d_stranz
28th May 2014, 01:06
The timer would have been my first option.

I agree.


but otherwise the timer keeps getting reset and no command gets sent.

That means the command won't be sent until the user finally releases the mouse. This will result in different behavior than with the keyboard, where each key repeat will result in an increment / decrement. If you want to emulate the same behavior, then you should first check to see if the timer is running and don't reset it if it is, just store the new value. When the timer does timeout, the command will be sent with the current value, and if the user is still pressing the mouse, the next event will start the whole timer process again for another cycle.

Edit -- sorry, on re-reading the original post, I realize I mixed up the mouse and keyboard. Nonetheless, the same thing holds - if you want the same apparent behavior for both mouse and keyboard, you have to let some updates go through instead of waiting until the user finally releases the key. If you really want it to be as close as a match between keyboard and mouse as possible, you shouldn't accept the current value on keyboard events, but only allow the same increment to occur as it would for a mouse event. Otherwise, the keyboard will increment the value much faster than the mouse will, so the changes on the hardware side will be "jumpier" with the keyboard versus the mouse.

SeanM
28th May 2014, 16:58
If you want to emulate the same behavior, then you should first check to see if the timer is running and don't reset it if it is, just store the new value. When the timer does timeout, the command will be sent with the current value, and if the user is still pressing the mouse, the next event will start the whole timer process again for another cycle.

I like this idea much better than my original one; it still allows for some commands to be sent out while incrementing the widget, but can be throttled to an appropriate rate for the connected device.

Thanks for the assist!