PDA

View Full Version : Idle()



qtoptus
16th July 2011, 20:43
How can I implement an idle event handler such that when the program is not processing user input events/GUI...? I tried the QTimer with interval 0 but it seems it calls the handler with non blocking manner that before returning from the event handler it may be called again...

mvuori
17th July 2011, 13:01
I don't know, but the traditional way to protect a handler is to use a flag to stop enty when previous processing is still underway:


void myProcessor()
{
static bool processing = false;

if (processing) {
return;
}
// processing =0 false
processing = true;
// now, do something
// ...done...
processing = false;
}







}

qtoptus
17th July 2011, 19:01
Thanks for your reply. I can give it a try but would not this lead to race conditions on the entry-flag so for instance just before it's set another call to the handler occurs...I'm assuming here the timer runs in a separate thread.
But if there's a way that I can hack into the application's main event loop and do something similar to traditional Win32 API non-blocking message loop (PeekMessage) that would be handy.

Santosh Reddy
18th July 2011, 01:23
If a timer slot does not return control, the next timer is not called, and all the event processing stops, it is in deed blocking the event loop execution. As you expect the timer is called only once and will not be called again unless you return the the control.

If you see (in your program), timer slot being called multiple times, then you are doing something in your code which cause it to happen. By default, if you don't return from timer slot, then it just stops processing all the events in the thread, where the timer lives.

qtoptus
2nd September 2011, 16:14
All the the timer callback does is refreshing the rendering canvas by calling the widget's update/repaint. I use Direct3D for rendering, so my guess is that an asynchronous calls of the timer's callback causes a deadlock like situation where some Direct3D commands are called again before other calls finish, or maybe the same commands called twice before they finish.
For example, a Direct3D device BeginScene is called again inside another BeginScene...

That's why I'm looking for some reliable way to handle idle state without resorting to a
"hack" solution which is the timer callback. :)

There must be a way to add and handle idle events like in other GUI toolkits...

Any idlea? ;)

qtoptus
2nd September 2011, 23:04
Ok so there's no idle event callback can be assigned to a Qt application, other than the timer hack...fair enough!

Santosh Reddy
3rd September 2011, 03:58
Well I will say you don't need a idle event handler generally in a event based framework like Qt. If you need to update a GUI regularly, you can as well do in a timer event (callback) and call update on the widget (don't call paint directly). When you call update it will queue required events to repaint the widget (if required) and the widget will repaint only after control returns to the event loop, back from timer event. You need to figure out how often you need to refresh the GUI, set that as timeout. Again if you know what causes the GUI to be re-painted / updated, you could call the update on the widget from that event directly rather than relying on a timer event.

wysota
3rd September 2011, 14:31
First of all it is not a hack and second of all you are obviously doing something wrong, the timer can't possibly trigger again before the previous iteration ends. I think you are getting some effect that incorrectly suggests that this is the case. For instance if you call update() from the timer's timeout slot, then it is true that timeout() might be called again before paintEvent() is executed (although it's unlikely). This is due to the fact that update() only schedules an event and doesn't do any repainting. However I agree with Santosh that you shouldn't need such calls at all. You need to update the canvas if it changes, there is no point in redrawing it with the same contents as before, it's just a waste of CPU cycles.

hakermania
4th September 2011, 22:00
First of all it is not a hack and second of all you are obviously doing something wrong, the timer can't possibly trigger again before the previous iteration ends. I think you are getting some effect that incorrectly suggests that this is the case. For instance if you call update() from the timer's timeout slot, then it is true that timeout() might be called again before paintEvent() is executed (although it's unlikely). This is due to the fact that update() only schedules an event and doesn't do any repainting. However I agree with Santosh that you shouldn't need such calls at all. You need to update the canvas if it changes, there is no point in redrawing it with the same contents as before, it's just a waste of CPU cycles.

Guessing the error is quite wow

qtoptus
5th September 2011, 18:42
However I agree with Santosh that you shouldn't need such calls at all

I disagree.


You need to update the canvas if it changes, there is no point in redrawing it with the same contents as before, it's just a waste of CPU cycles.

Well there's a big point :) when you are working on a robust application such as CAD. Otherwise this suggests that video games waste CPU cycles all the time :)
Nope it's mainly GPU cycles, and they are not wasted since they are not in use when the scene is not changing. ;)

wysota
5th September 2011, 19:22
Otherwise this suggests that video games waste CPU cycles all the time :)
If they resend the same frame multiple times then they do. If you have a 60Hz display, you can render even 1000000FPS but you will only see 60. The rest is wasted.

qtoptus
5th September 2011, 20:41
If they resend the same frame multiple times then they do

How would you resend the same frame multiple times and why? Put it in a loop inside the "timer" or the idle event?

Well I can set the timer to 60 FPS ;) Done!

wysota
5th September 2011, 23:20
How would you resend the same frame multiple times and why?
Don't ask me. It's you who said that you don't agree that a new frame should be generated only when something on the display changes.

Well I can set the timer to 60 FPS ;)
Sure you can. But this won't give you 60 FPS.

qtoptus
6th September 2011, 17:26
It's you who said that you don't agree that a new frame should be generated only when something on the display changes.

Frame generation vs. rendering.


Sure you can. But this won't give you 60 FPS.

Then what 70, 80, 10 FPS?

wysota
7th September 2011, 08:11
Frame generation vs. rendering.
So you want to generate 10 frames but display 10000 frames? In my opinion it is much better to generate 10 frames and display 10 frames (or less if the hardware can't keep up).


Then what 70, 80, 10 FPS?
Setting the timer to 60 fps will give you less than 60 frames per second top.