Emitted signals only processed once per event loop...
-
Hi all,
Is there an easy way to configure a signal/slot to only be called once per event loop, even though its been emitted multiple times from different places in the code. Say I have a function that changes state, but calls other function that changes sub-states all those state changes emitting signals to refresh UI, auto-savings, or other. I'd like the slot to be called only once for the whole event loop.
I know I can deal with that manually with tracking the calls and state, and use a timer to reset state. However, I was wondering if there was a mechanism in Qt to say 'this signal should only be called once per event loop' so its handled internally instead of manually by the application developer.
Thanks.
-
I took a look, and while there are different types of connections, there isn't a type that matches what I need, which is unfortunate. There is the following flag: SingleShotConnection, but it will be a SingleShot over the whole application (signal is automatically disconnected once emitted). I wish there was something like SingleShotConnectionPerEventLoop or something like this.
-
How should this work? What is one event loop call? Someone might call process events somewhere - should count this too? Use a timer.
-
Qt has nothing like this built in. Usually, there is a solution with two timers: The first is always reset when the slot should be called. During this short interval, more slot calls can be collected. However, this might delay indefinitely. Hence, there should be a second timer which is not reset while it is running and after a longer period (longer than the first timer) still calls the slot.
In the specific case of refreshing the UI: Just call
update()
. This one has what you want built in. It will not always just fire away. If you want to force an immediate redraw there isrepaint()
. -
Thank you @SimonSchroeder. But I am not sure update() does what I need, not in terms of calling it just once, but in terms of updating the UI properly when values change. The way I do things right now is:
- File loaded -> send signals -> change all values in UI (ie: update())
- A selection has changed in some comboBox -> send signals -> change necessary values in UI (ie: update())
- But what I am running into is the following:
- File loaded -> send signals etc... When values change, the comboBox selection also changed -> send signal -> change necessary values in UI. Now the File loaded will change the same UI that the comboBox selection has triggered. Results in the UI update being called twice.
I hope that makes sense. I am not sure update() on a widget does that. I think update() is just to trigger a repaint of some widget because its content has changed.
-
Use a single-shot 0 timer. Operations can request a service by starting the timer. The request can be repeated as many times as desired, but the timer will only fire once when the event loop next has a chance to service the timer event.
QCoreApplication app(argc, argv); QTimer zeroTimer; zeroTimer.setInterval(0); zeroTimer.setSingleShot(true); zeroTimer.callOnTimeout( []{ qDebug() << "timeout"; } ); zeroTimer.start(); zeroTimer.start(); app.exec();
-
Thank you @SimonSchroeder. But I am not sure update() does what I need, not in terms of calling it just once, but in terms of updating the UI properly when values change. The way I do things right now is:
- File loaded -> send signals -> change all values in UI (ie: update())
- A selection has changed in some comboBox -> send signals -> change necessary values in UI (ie: update())
- But what I am running into is the following:
- File loaded -> send signals etc... When values change, the comboBox selection also changed -> send signal -> change necessary values in UI. Now the File loaded will change the same UI that the comboBox selection has triggered. Results in the UI update being called twice.
I hope that makes sense. I am not sure update() on a widget does that. I think update() is just to trigger a repaint of some widget because its content has changed.
Have a look at QObject::blockSignals(bool block) and QSignalBlocker
https://forum.qt.io/topic/129364/blocking-signals-to-child-widgets/7