February 17, 2011

julio jerez julio jerez
Lab Rat
54 posts

How to make a QGLWidget a real time game loop?

Page  
1

I am trying to make my runtime window a real time window,
I know that many demos use a timer to send and updates message to a WGLWdiget like this

  1. m_animationTimer.setSingleShot(false);
  2. connect(&m_animationTimer, SIGNAL(timeout()), this, SLOT(OnIdle()));
  3. m_animationTimer.start(2);

However the timer method has few short comings:
First the granularity is too course (milliseconds instead of microsecond).
Second it requires lots of management when you want to stop for example to do some other actions.
the timer keeps sending even to the update in the middle of other operations, and you end up with flags and other stuff
just to control the logic.

Usually other GUIs have an event that is called when the system have no more Event in the event Queue. So to set a Real time Update all the client application need to do is to trap the Idle Event and from there send the Update to the Gl window.
This automatically controls the event queue to never overflow and the also the update stop each time
any other message is send to the system.
I am assuming that QT also have to have and Idle Event that is call when no more message are pendim, but I cannot find it.
Can someone tell me how to do this, please?

16 replies

February 17, 2011

julio jerez julio jerez
Lab Rat
54 posts

What I am doing is that I am setting my Own Even Handle

  1. class newtonDemosEventFilter: public QObject
  2. {  
  3.  Q_OBJECT
  4.  protected:  
  5.  bool eventFilter(QObject *obj, QEvent *ev);  
  6. };
  7.  
  8. bool newtonDemosEventFilter::eventFilter(QObject *obj, QEvent *ev)  
  9. {    
  10.  // I want to know what code is the one for want the application is Idle so thar I can send one even to update my WGLWidget
  11.  if (ev->type() == QEvent::What_is_the_Idle_Evene?) {
  12.   // what event to send to force a WGLWidget update?
  13.  }
  14.  
  15.  return QObject::eventFilter(obj, ev);  
  16. }
  17.  
  18.  
  19. int main(int argc, char *argv[])
  20. {
  21.  // Enable run-time memory check for debug builds.
  22. #ifdef _MSC_VER
  23.  _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
  24. #endif
  25.  
  26.  // Set the memory allocation function before creation the newton world
  27.  // this is the only function that can be called before the creation of the newton world.
  28.  // it should be called once, and the the call is optional
  29.  NewtonSetMemorySystem (newtonDemos::PhysicsAlloc, newtonDemos::PhysicsFree);
  30.  
  31.  
  32.  QApplication aplication(argc, argv);
  33.  newtonDemosEventFilter filter;
  34.  
  35.  newtonDemos demos;
  36.  demos.show();
  37.  
  38.  aplication.installEventFilter(&filter);
  39.  return aplication.exec();
  40. }

But I am stoked find the idle event.

February 17, 2011

Tobias Hunger Tobias Hunger
Mad Scientist
3137 posts

I really do not understand what you want to do. Why would you want to paint whenever the event loop is empty?

I do understand a “paint after each event” or “paint x frames per second”, but why would you want to paint whenever the event queue is empty?

PS: How is ‘render whenever the event queue happens to be empty’ realtime?

February 17, 2011

julio jerez julio jerez
Lab Rat
54 posts

Whent you are making an application like a video Game or a performace measuring tool, you need the application to update as fast as it can. That is why you draw after all events are processed.
It is a very standrad operation in all operating system and all GUIs I know.

A timer is a very, very bad Idea.

February 17, 2011

Bradley Bradley
Lab Rat
314 posts

Try the aboutToBlock [doc.qt.nokia.com] signal.

 Signature 

Nokia Certified Qt Specialist.

February 17, 2011

julio jerez julio jerez
Lab Rat
54 posts

I see that class QAbstractEventDispatcher seems to have what I look for,
but hwo do I use that class
I do not see a single example using a class like tha in the demos.

I tryed this

  1. //class newtonDemosEventFilter: public QObject
  2. class newtonDemosEventFilter: public QAbstractEventDispatcher  
  3. {  
  4.  Q_OBJECT
  5.  protected:  
  6.  bool eventFilter(QObject *obj, QEvent *ev);  
  7. };

but all I get is a bunch of errors.

February 17, 2011

julio jerez julio jerez
Lab Rat
54 posts

for what I can see thsi si too low level, It is asking me to impelmnet all thsi funtions

1> due to following members:
1> ‘bool QAbstractEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags)’ : is abstract
1> c:\newton-dynamics_new\packages\thirdparty\qt\4.7.1\include\qtcore\../../src/corelib/kernel/qabstracteventdispatcher.h(71) : see declaration of ‘QAbstractEventDispatcher::processEvents’
1> ‘bool QAbstractEventDispatcher::hasPendingEvents(void)’ : is abstract
1> c:\newton-dynamics_new\packages\thirdparty\qt\4.7.1\include\qtcore\../../src/corelib/kernel/qabstracteventdispatcher.h(72) : see declaration of ‘QAbstractEventDispatcher::hasPendingEvents’
1> ‘void QAbstractEventDispatcher::registerSocketNotifier(QSocketNotifier *)’ : is abstract
1> c:\newton-dynamics_new\packages\thirdparty\qt\4.7.1\include\qtcore\../../src/corelib/kernel/qabstracteventdispatcher.h(74) : see declaration of ‘QAbstractEventDispatcher::registerSocketNotifier’
1> ‘void QAbstractEventDispatcher::unregisterSocketNotifier(QSocketNotifier *)’ : is abstract
1> c:\newton-dynamics_new\packages\thirdparty\qt\4.7.1\include\qtcore\../../src/corelib/kernel/qabstracteventdispatcher.h(75) : see declaration of ‘QAbstractEventDispatcher::unregisterSocketNotifier’
1> ‘void QAbstractEventDispatcher::registerTimer(int,int,QObject *)’ : is abstract
1> c:\newton-dynamics_new\packages\thirdparty\qt\4.7.1\include\qtcore\../../src/corelib/kernel/qabstracteventdispatcher.h(78) : see declaration of ‘QAbstractEventDispatcher::registerTimer’
1> ‘bool QAbstractEventDispatcher::unregisterTimer(int)’ : is abstract
1> c:\newton-dynamics_new\packages\thirdparty\qt\4.7.1\include\qtcore\../../src/corelib/kernel/qabstracteventdispatcher.h(79) : see declaration of ‘QAbstractEventDispatcher::unregisterTimer’
1> ‘bool QAbstractEventDispatcher::unregisterTimers(QObject *)’ : is abstract
1> c:\newton-dynamics_new\packages\thirdparty\qt\4.7.1\include\qtcore\../../src/corelib/kernel/qabstracteventdispatcher.h(80) : see declaration of ‘QAbstractEventDispatcher::unregisterTimers’
1> ‘QList<T> QAbstractEventDispatcher::registeredTimers(QObject *) const’ : is abstract
1> with

I am lost here, this is so eassy to do in Windows and WxWidget,
there has to be a way to do this eassy in Qt.
so far everything else has being very eassy.

February 17, 2011

kkrzewniak kkrzewniak
Lab Rat
218 posts

From Qt’s documentation:
A QTimer with a timeout interval of 0 will time out as soon as all the events in the window system’s event queue have been processed.

 Signature 

Me, Grimlock, not “nice dino”. ME BASH BRAINS!

February 17, 2011

Bradley Bradley
Lab Rat
314 posts

  1. connect(QAbstractEventDispatcher::instance(), SIGNAL(aboutToBlock()),
  2.         this, SLOT(onAboutToBlock()));

 Signature 

Nokia Certified Qt Specialist.

February 17, 2011

julio jerez julio jerez
Lab Rat
54 posts

I saw that but when I do this

  1. m_animationTimer.setSingleShot(false);
  2. connect(&m_animationTimer, SIGNAL(timeout()), this, SLOT(OnIdle()));
  3. m_animationTimer.start(0);

kkrzewniak wrote:
From Qt’s documentation: A QTimer with a timeout interval of 0 will time out as soon as all the events in the window system’s event queue have been processed.

I saw that but this is what I was explaining above, the timer send events asynchronously even when other event are being proccesed, not when the queue is empty.
This is importnat because this application is running a sevral threads on teh background.
if for example I go to the menu and a Load a different scene, the render should stops,
but is does not so the mommnet I click I get all kind of rasing conditions.
I suppose I can fix that but tha was not nessesary before.

when I set it to this

  1.  m_animationTimer.setSingleShot(false);
  2.  connect(&m_animationTimer, SIGNAL(timeout()), this, SLOT(OnIdle()));
  3.  m_animationTimer.start(0);
  4.    

It update as fast as it can, but still have the problem that if you click on en menu for example the timer still update send even and it should stops, because there are other events with higher priority.
Basically I need the updates if and only if when the system has nothing else to do.

To Bradley I see it is a signal, I read the explanation of that signal and it is no clear to me by I will experiment with that,
I see that there are other signals as well.

February 17, 2011

julio jerez julio jerez
Lab Rat
54 posts

Bradley wrote:
  1.  connect(QAbstractEventDispatcher::instance(), SIGNAL(aboutToBlock()), this, SLOT(onAboutToBlock())); @</blockquote>
  2.  
  3. That does part of what I want but still not exacty, because it does update as fas as it can  
  4. however it still send the same sinal when I click on the menu.
  5. I need tha teh signal to be the lowest possible priority of all signals.
  6.  
  7. Maybe I did it wrong, I implemenetd like this
  8.  
  9. @connect(QAbstractEventDispatcher::instance(), SIGNAL(aboutToBlock()), this, SLOT(OnIdle()));
  10.  
  11. ...
  12.  
  13.  
  14. void newtonDemos::OnIdle()
  15. {
  16.  m_canvas->update();
  17. }

is that how is supposet to be?

February 17, 2011

Bradley Bradley
Lab Rat
314 posts

You are probably causing a cycle. The update() call will probably post an UpdateRequest event, and after it is processed (and any other events), the aboutToBlock signal will be sent again, which will cause another update() call.

 Signature 

Nokia Certified Qt Specialist.

February 17, 2011

julio jerez julio jerez
Lab Rat
54 posts

so I though somethomg liek this shopuld do it, but it does not

  1. void newtonDemos::OnIdle()
  2. {
  3.  static bool updateCanvas;
  4.  if (updateCanvas) {
  5.   updateCanvas = true;
  6.   m_canvas->update();
  7.   updateCanvas = false;
  8.  }
  9. }

what does “a funtion that coul block” means?
bq. This signal is emitted after the event loop returns from a function that could block.

February 17, 2011

julio jerez julio jerez
Lab Rat
54 posts

For what I can see the only way I can do this is by having a bool that is toggled on each action/slot,
and that does not sound like an elegant or atractive solution.

I can not beleive this is not a trivial operation in Qt.
This is the default behavior in window

February 17, 2011

julio jerez julio jerez
Lab Rat
54 posts

I can upload the two application to my server and post a link to it maybe some one can
take a look and tell me how to do what I want.
the window and the QT.

February 17, 2011

julio jerez julio jerez
Lab Rat
54 posts

Well I could not find a clean way to do it, but it does no matter, I can acomplishe the same in diffrnet way
I end up doing this

  1. void newtonDemos::OnIdle()
  2. {
  3.  if (m_doVisualUpdates) {
  4.   m_canvas->update();
  5.  }
  6. }

and I set m_doVisualUpdates on and off on eh relvane Menu actions.
It is still better than using a timer, and I also learned a lot about trapping events wih Qt.
Thank every one for the help.

Page  
1

  ‹‹ Scrollbars on a QGLWidget      using a QGraphicsView as the viewport for a (different) QGraphicsView? ››

You must log in to post a reply. Not a member yet? Register here!