Results 1 to 6 of 6

Thread: QTimer ->start(0) + OpenGL + resize/move window => crash

  1. #1
    Join Date
    Jul 2008
    Posts
    10
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Wink QTimer ->start(0) + OpenGL + resize/move window => crash

    Hi,

    I've got an issue with OpenGL.
    I've got a QMainWindow (loaded from a .ui), that include a QGLWidget, well in fact an instance of a personnalize class that inherits from QGLWidget, ...

    Actually I'm migrating an SDL+OpenGL application into a QT 4.4 + OpenGL app
    It's kind of a 3D cloud points viewer.

    Ok by now everything works, I see the scene, I can interact with it (keyboard, mouse), but it's not perfect.

    In the first time my idea was to do like in SDL : an infinit while(true) loop.
    I managed to do that with this code in constructor :
    Qt Code:
    1. connect(&qTimerRedraw, SIGNAL(timeout()), this, SLOT(dessiner()));
    2. qTimerRedraw.start(0); // CPU = 100%
    To copy to clipboard, switch view to plain text mode 

    As the comment explains, it's pretty obvious that one core is going to be at 100% because of the QTimer interval set to 0. And I really don't care if so, because I know how to slow down the framerate in order to reduce the CPU usage. (I could also see the FPS in live).
    It's great, very fluid with key events (stay pressed, release, ...).

    The problem is that : my application is sometimes crashing when I move the window or when I resize it. Precisely, the crash occurs when i release the mouse button. Why does this crash appears errraticaly ?
    I tried to QDebug ResizeGL() without success.

    After I realize the bug was due to the infinite signal<->slot loop, I had a second idea : pause the timer during the "work time" :
    Qt Code:
    1. void gldrawer::paintGL()
    2. {
    3. qTimerRedraw.stop(0); // wait before the end
    4.  
    5. // paint job ... (heavy work)
    6.  
    7. qTimerRedraw.start(0); // restart
    8. }
    To copy to clipboard, switch view to plain text mode 

    This might be a good idea with a long "work time" but it doesn't resolve my issue.

    My third idea was a different approch : during my research I discover that lots of example works in another way to handle user interaction. The scene is refreshed only when a user interaction leads to a repaint (keyboard or mouse event typically).
    That is a very good idea because you do not need to do an infinite loop (100%CPU) so it was solving my problem in 2 ways :
    -no loop => no crash when moving or resizing
    -my application does not have animations, it's only when the user interact that I have to redraw

    So I made modifications to my code, but now there is another problem : keys events.
    -I can't use modifiers like SHIFT, ALT, ...
    ->I can't check the modifiers during a keyPressEvent call
    ->It stops the other key :
    i see keyReleaseEvent calls even if i stay pressed, what the ??!
    -When you constantly press a key, the reaction is like in a text application : small delay before the event is fire continously

    In the two solutions, the application is fluid when the user keeps the key down, so that's cool. But in both cases, I've got glitches...
    What is the best thing to do ? How can I fix my problems ?

    Do I need to post some code ?

    Thanks!
    Last edited by jacek; 3rd July 2008 at 22:19. Reason: changed [qtclass] to [code]

  2. #2
    Join Date
    Oct 2006
    Posts
    279
    Thanks
    6
    Thanked 40 Times in 39 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QTimer ->start(0) + OpenGL + resize/move window => crash

    Your third approach seems to be correct since you aren't using animations.
    Use QKeyEvent::isAutoRepeat () to find out if your handling an 'real' key press.
    For fluid motion when a key is pressed i suggest you start a timer when a key is pressed and kill it when all keys have been released. You could use a QSet to keep track of pressed keys.

    Qt Code:
    1. //member
    2. QSet<int> pressedKeys;
    3.  
    4. void keyPressEvent(QKeyEvent* e)
    5. {
    6. if(e->isAutoRepeat())
    7. return;
    8. if(pressedKeys.isEmpty())
    9. startTimer(40);
    10. pressedKeys.insert(e->key());
    11. }
    12.  
    13. void timerEvent(QTimerEvent* e)
    14. {
    15. if(pressedKeys.contains(Qt::Key_Up))
    16. ...;
    17. if(pressedKeys.contains(Qt::Key_Left))
    18. ...;
    19. updateGL();
    20. }
    21.  
    22. void keyReleaseEvent(QKeyEvent* e)
    23. {
    24. pressedKeys.remove(e->key());
    25. if(pressedKeys.isEmpty())
    26. startTimer(40);
    27. }
    To copy to clipboard, switch view to plain text mode 
    This way you should be able to catch any combination of keys being pressed.

  3. #3
    Join Date
    Jul 2008
    Posts
    10
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Red face Re: QTimer ->start(0) + OpenGL + resize/move window => crash

    I'm going to kill me. This crash was due to a simple division by 0 in my FPS counter. ahah
    I discover it after compiling debug libraries and try a debug...
    At least I discover some QT functionnalities...

    Qt Code:
    1. last_time = current_time;
    2. current_time = QTime::currentTime();
    3. elapsed_time = (current_time.second()*1000 + current_time.msec()) - (last_time.second()*1000 + last_time.msec());
    4. [B]this->fps = 1000 / elapsed_time;[/B]
    To copy to clipboard, switch view to plain text mode 


    I don't exactly know why elapsed_time could be set to 0, at least I know it was (only) happening on some resize events.
    I'm guessing it's due to the functions call order ; my guest is that :
    -when a resize event happens it stops the current function execution
    -the rest of the code is not executed until and of resize
    -... i don't know

    i just did a test and of course, during a resize, my infinite loop function is not called

    whatever, this solved my problem :

    Qt Code:
    1. if(elapsed_time <= 0)
    2. this->fps = 0;
    3. else
    4. this->fps = 1000 / elapsed_time;
    To copy to clipboard, switch view to plain text mode 


    so simple....

    I'm gonna check on your tips in the following days spud, thanks for helping !
    If it works I will improve a LOT my application.

    A little preview right there:
    Last edited by jacek; 3rd July 2008 at 22:19. Reason: changed [qtclass] to [code]

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QTimer ->start(0) + OpenGL + resize/move window => crash

    Quote Originally Posted by anthibug View Post
    elapsed_time = (current_time.second()*1000 + current_time.msec()) - (last_time.second()*1000 + last_time.msec());
    Take a look at QTime::msecsTo().

  5. #5
    Join Date
    Jul 2008
    Posts
    10
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTimer ->start(0) + OpenGL + resize/move window => crash

    Thanks jacek, I missed it !

    Thanks spud you got the idea : a timer to refresh the scene if their is still a pressed key....
    I managed to do this with minor modifications :

    Qt Code:
    1. void gldrawer::keyPressEvent(QKeyEvent * event)
    2. {
    3. if(event->isAutoRepeat())
    4. return;
    5. if(_activeKeystates == 0)
    6. qTimerRedraw.start(0);
    7. for(KeyStates::iterator it = _keystates.begin();it != _keystates.end();
    8. it++)
    9. {
    10. if (event->key() == it->first)
    11. {
    12. it->second = true;
    13. _activeKeystates++;
    14.  
    15. break;
    16. }
    17. }
    18. }
    19.  
    20. void gldrawer::keyReleaseEvent(QKeyEvent * event)
    21. {
    22. for (KeyStates::iterator it = _keystates.begin();it != _keystates.end();
    23. it++)
    24. {
    25. if (event->key() == it->first && !event->isAutoRepeat())
    26. {
    27. it->second = false;
    28. _activeKeystates--;
    29. break;
    30. }
    31. }
    32. if(_activeKeystates == 0)
    33. qTimerRedraw.stop();
    34. }
    To copy to clipboard, switch view to plain text mode 

    where _keystates is a std::map<Qt::Key, bool> (yes I know I could use QMap, I will ...)

    Right now CPU is at 0%.
    If I push a key (and stay pushed) the scene is continously refreshed : one core is at 100%.
    I can push keys with modifiers :-)

    Thanks !


    ----


    I'm currently having problems dealing with QSlider :
    I have to repaint the scene during a call to my slot corresponding to the "valueChanged" signal of the QSlider. The problem is that it's make the slider freeze/lag.
    In can understand that because each time I move the slider it redraws the scene, and that takes time.
    The scene is updated in real time according to the position of the slider, but the position of the slider itself is lagging (juste visually)...
    Could be a user issue in the future.
    I tried the "sliderReleased()" but the problem is that the scene is not updated in real time.
    Last edited by anthibug; 7th July 2008 at 15:32.

  6. #6
    Join Date
    Jul 2008
    Posts
    10
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTimer ->start(0) + OpenGL + resize/move window => crash

    I managed to do that the same way I did with the keys :
    -if the QSlider is moved then repaint (qTimerRedraw.start(0)
    -when released stop to repaint

    ... so easy

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.