Is there kind of of non-queued QEvent?
-
In my code I may set a flag one or more times, as a kind of event. In the main windows loop I would like to check this flag and if set execute a service routine, just once, and reset the flag. Note this service routine is only executed once regardless of how many times the flag was set. What Qt facility is most appropriate for implementing this flag and setting up the service routine. QEvent does not seem quite appropriate for it is queue based, and multiple event raisings are not - I presume - combined into a single response.
-
@powerapproach said in Is there kind of of non-queued QEvent?:
QEvent does not seem quite appropriate for it is queue based, and multiple event raisings are not - I presume - combined into a single response.
QEvent
s themselves are not "queue based". Qt event loops are, but notQEvent
s.If you really need immediate, instantaneous reaction to something you might need @mpergand's
sendEvent()
.But I see nothing in your description which demands that. What is wrong with a normal signal which the main loop will pick up in the normal fashion?
As for the " I would like to check this flag and if set execute a service routine, just once, and reset the flag.". On the one hand you only want to execute the service routine, yet on the other hand you say you want to "reset the flag" presumably to allow it to be executed again in the future. You need to define the "boundary" for this action --- when it can be reset/re-actioned relative to when the event potentially occurs multiple times. It does not matter whether you use an "event" or a "signal" you will still have to have a mechanism of your own to decide this, Qt certainly won't know.
-
@powerapproach I don't know of anything Qt provides directly. You could have a look at
QWidget::update()
as this slot will fold several entries in the event queue into one. A much easier approach would be to check the flag before emitting the signal. Only emit the signal when you are about to change the flag. Or in reverse: inside the slot check if the flag is supposed to change. If it does not change, return immediately. -
@JonB Thanks for your reply. I do not need instantaneous reaction. A flag may be set multiple times within various widgets, but I only want to service this set flag one time only, once Qt has returned to the main loop. The flag is reset in the service routine, allowing the process to be repeated. The problem with signals is they cause instantaneous calls to the targeted slot, so if I emit from several places within widgets, the slot gets executed multiple times - not the effect I want.
Put most simply, I can implement the flags simply, what I need to know is how to insert a service routine into the main loop (i.e. waiting on another mouse/keyboard, etc interaction). Maybe there are preexisting classes within Qt that support this. QEvent does not seem to be it, or perhaps I am mistaken. I do not not have a particularly clear idea of Qt's structure, admittedly.
-
@powerapproach said in Is there kind of of non-queued QEvent?:
I do not need instantaneous reaction. A flag may be set multiple times within various widgets, but I only want to service this set flag one time only, once Qt has returned to the main loop. The flag is reset in the service routine, allowing the process to be repeated.
Actually, this problem is quite common. The trick is usually using two different timers. The first timer is the minTimer. Here, you will have a short delay. The timer is started when your slot is called the first time. If within this time the slot is called additional times, the minTimer is restarted. So, whenever there are multiple repeated calls to the slot within a short amount of time (the timeout time of minTimer) the call to the actual slot (your current slot that does the actual work) gets further delayed. Once this minTimer is allowed to timeout it will trigger your current slot. Normally, this could delay indefinitely. This is why there is usually also a maxTimer. The maxTimer gets a much larger delay compared to the minTimer. Whereas the minTimer is reset every time the maxTimer is only started when it is not yet running. Once the maxTimer stop your current slot is executed.
I didn't find what I was looking for when I googled it, but here https://github.com/Diaoul/Dobby/blob/master/dobby/qt/timers.py you will find an example implementation (in Python) of the approach I described (haven't fully checked the code, though).
-
@SimonSchroeder Thank Simon for this solution - I’ll check it out. It is a work-around of course. Do you know if there is any means of executing a routine at each OS “tick”? This would be a rough equivalent of being able to insert a call into the GUI wait loop, as far as this application goes.
-
@powerapproach said in Is there kind of of non-queued QEvent?:
Do you know if there is any means of executing a routine at each OS “tick”?
You can have a repeating QTimer with a timeout of 0. It will fire when your event loop is idle. So, this approach will be the fastest you can get without blocking everything else. Although, an idle timer also means that you will permanently fully utilize a single CPU core. Users of your app might not expect this behavior.
-
@SimonSchroeder Ok thanks for that