I have a QGridLayout
with a lot of widgets, which I need to resort quite often. I do this, by replacing them one by one in the newly sorted order.
That means, however, that with every added widget the layout wants to update itself and redraw its children, which causes a lot of unnecessary slowdown.
I would like to tell the layout to just not do any layouting or drawing, until I'm done adding everything that I want to add.
I'm trying to do this by overwriting the update()
method and only calling the parent method, once I am done adding all the widgets.
def update(self):
self._fill_layout()
super(MyLayout, self).update()
That still does not seem to remove all the slowdown, so I also catch all calls to setGeometry()
and only call its parent version 20ms after the last call to it was made.
def setGeometry(self, screen_rect=None):
if screen_rect is not None:
self._last_requested_geometry = screen_rect
self._delayed_redraw_timer.start(20)
else:
# called by our timer
return super(MyLayout, self).setGeometry(self._last_requested_geometry)
This, however, causes some widgets to be displayed, while they are not part of the layout and just part of the parent widget (I assume, since they are positioned in the top left corner and larger than they should be. So they seem to be painted, while I am still layouting them.
I installed an event filter to the widgets and depending on if they are in a layout or not. But this seems to have the opposite effect, since the widgets are not painted now (more precisely, only the background is). I assume that the paint event, which causes me trouble, is blocked, but no other comes afterwards, so they are put into the layout but not redrawn anymore?
def eventFilter(self, watched, event) -> bool:
if event.type() == QEvent.Paint:
return watched.layout() is None
return False
I tried fixing this by manually triggering a redraw, with self.parentWidget().repaint()
inside the layouts update
method, but this does not change anything. The widgets are still not showing.
Is there an easier way to tell the layout to only calculate itself, without updating its visuals and then trigger that paint event manually?