Multiple "valueChanged"-events in QSlider
-
Hello,
I noticed some strange behavior with the valueChanged event in QSlider (I'm currently porting from QT3 where I didn't have those problems).
When I click on an arrow to increment or decrement the slider by one, I receive a valueChanged event. So far so good. But when I do some lengthy computing in a method receiving this event, I will get another valueChanged event - just as If I would have been on the arrow with the mouse for a longer time.
Is there any way to inhibit this behavior? Maybe some property not to react on a mouse held on the arrow?
Any help would be appreciated.
Thanks a lot
-
The complicated way is to catch the mouse events, let's skip this. The not so complicated is to block the signal during your process. Like this:
@void yourapp::sliderchanged(int)
{
ui->yourslider->blocksignals(true);... long process ...
ui->yourslider->blocksignals(false); // back to normal
}@Another possibility is to use somewhere (maybe at the start) in your function the
@qApp->processEvents();@
where your computing will stop for a bit to receive all application events.
Hope this helps.
-
Thanks a lot,
"blockSignals" solves the problem.
Thank you for your fast answer ! -
The problem with blocking signals is that it blocks the later ones - that is, if you slide from 1 to 10, it will process 1 although (I guess) the more important one would be 10.
If this is undesired, you can use delayed processing of some sorts - add a timer (for eg QBasicTimer) and start it when you get sliderchanged event. Set the delay to be around 100ms.
When you get the last signal, no new ones will appear in the next 100ms and you can freely process the single event. (this is something that is usually done when people implement incremental search)
-
Mmh, that's a point.
But I read in the QT-documentation, that QBasicTimer is just for internal use and QTimer should be used instead of.I try it with QTimer::singleShot with 100ms delay. That should be fine too.
-
As a general point it is important to avoid doing something in the event handling that takes a lot of time exactly for this kind of problems.
It will block your applications repainting as well because spending time in your calculation at every event will mean you will have less time to repaint.
This is important since the signal you respond to; valueChanged() is emitted before the result of that is painted on screen. So the user will not see the slider move until your calculation is done. If the user moves around the mouse a lot this can cause the repaint to not happen for various seconds. That will look ugly :)
The solution is to make your slot return very quickly; it can be something as simple as
<pre>
m_timer.stop(); //stop previous running timer
m_timer.start(); // handle the change in 800ms or so
</pre>Then your timer can read the current value from the slider and do its calculation at most only once per timeout. Making sure that the screen keeps updated in between.
-
Well, what shoud I say?
Thanks for so much help!
It really solves the problem.