QGraphicsScene taking long to update
-
I am trying to get a
QGraphicsScene
to update at a fixed rate with a timer.An example of what I'm trying to achieve is to animate a rectangle moving across the screen with its
x
position being incremented every frame (for example at120 fps
). However, when callingupdate()
on theQGraphicsScene
, it takes about16 msec
to complete (even when the scene is empty, as in the example below). This caps the frame rate at about 60, and the slowdown accumulates if there is more than one QGraphicsScene that needs to get updated.
What is the right way to go about this?
Thanks!import qt class View(qt.QGraphicsView): def __init__(self): qt.QGraphicsView.__init__(self) self.setScene(qt.QGraphicsScene()) class Window(qt.QDialog): def __init__(self): qt.QDialog.__init__(self) self.setLayout(qt.QVBoxLayout()) self.view = View() self.view.setViewportUpdateMode(qt.QGraphicsView.NoViewportUpdate) self.layout().addWidget(self.view) self.btn = qt.QPushButton('Start') self.btn.clicked.connect(self.clicked) self.layout().addWidget(self.btn) self.time = qt.QTime() self.timer = qt.QTimer() self.timer.timeout.connect(self.runUpdate) self.frame = 0 self.dontUpdate = False def clicked(self): self.timer.start(1) def runUpdate(self): self.frame += 1 self.time.start() if not self.dontUpdate: self.view.scene().update() print(self.time.elapsed(), qt.QTime.currentTime().msec(), self.frame) app = qt.QApplication([]) window = Window() window.show() app.exec_()
Note: the script above is using the following python module (qt.py),
from PySide2.QtCore import * from PySide2.QtGui import * from PySide2.QtWidgets import *
-
-
Hi most gfx card can turn off Vsync
Not that screen can draw any faster regardless but it allows u to puch more frames. -
Hi,
To get any faster you'll likely have to consider going OpenGL.
What kind of animation do you have ? And do you really need to reach 120fps ?
-
@SGaist
Thanks for suggesting OpenGL, I think that might be a possibility at some point.
As of now, I got it to work by locking the UI updates and batch repainting all of the windows at once:for(auto widget : qApp->topLevelWidgets()){ widget->setUpdatesEnabled(true); } qApp->processEvents(); for(auto widget : qApp->topLevelWidgets()){ widget->setUpdatesEnabled(false); }
I know this may not be the best way to achieve this, so I am all ears if there's any better way to limit UI updates to a single point in execution.
Thanks!