PDA

View Full Version : How to avoid redraw of widgets outside visibleRegion on update? [PyQt5]



DDR
24th May 2019, 05:54
I have subclassed a widget, a QSlider, and styled it so it has large transparent margins. This makes it much easier to grab on a touchscreen. However, the margin extends under some buttons to the right of the slider. This causes the buttons to redraw when the slider is moved, which is very slow. If I make the slider narrow, so it does not have the margins, then it renders fast and the buttons do not redraw. I think I would like the margins to exist for the purposes of touch detection, but not for the purposes of dirty rect propagation.

I tried to change the visible region the paint event, but it only affected the slider drawing itself - it did not affect the buttons being redrawn.


def paintEvent(self, evt):
clippedEvt = QPaintEvent(self.visibleRegion())
super().paintEvent(clippedEvt)

So I downloaded the source code, and in qt-everywhere-opensource-src-5.7.1/qtbase/src/widgets/kernel/qwidget.cpp:10966, in the QWidget::update function, it looked like it was responsible for figuring out where the update rect was. I think it just uses the bounding box of the widget.

I would like to use the visual bounding box, however, instead of the real one, for the purposes of repainting. To do this, I tried overriding the update function in my subclass, like this:


def update(arg):
print('update event', arg)

However, I can not get my slider to print update event. It appears it still uses the parent class' update event to schedule updates.

So I tried overriding the rect function, because I see update uses that. I don't think this will work, since I bet this is also used for touch intersection calculation. But it is no matter, because it too has no effect.


def rect(self):
print('update rect')
return QRect(30, 10, self.width()-30, self.height-10)


Is there another way to make my widgets, far away and above the transparent margin, not redraw themselves? Or have I taken the wrong approach?

Thanks!
–DDR

anda_skoa
24th May 2019, 08:45
Neither QWidget::update() nor QWidget::rect() are "virtual" in C++, thus they cannot be overridden.

How did you end up with the slider and button overlapping?
Even if the slider's drawing is only occupying a part of its area, the layout should still have position the button outside of the slider's bounding box.

Cheers,
_

d_stranz
24th May 2019, 18:15
the layout should still have position the button outside of the slider's bounding box.

Sounds like maybe the OP isn't using layouts to position the widgets.

DDR
30th May 2019, 00:10
I couldn't figure out how to shift the slider to one side or the other, so I just made the slider wider than it needed to be and buried the unwanted space under some buttons to the side. (I wanted the hit rect of the slider handle to be larger than the visible handle, because I'm working with a questionable $12 touchscreen, so I added a bunch of invisible padding to it.)

13142

In this screenshot, we see the touch area drawn as green. (This is normally drawn transparent.) Even if you miss the slider by a small margin, you can still drag it without any issue. The green area used to extend out a few pixels to the left and right, so it was even easier to drag. However, this caused the text on the buttons to get redrawn so I narrowed it. But now it's harder to drag.

Added after 6 minutes:

Oh, sorry, missed your reply there.


Sounds like maybe the OP isn't using layouts to position the widgets.

That is correct. Proper layouts are both hard to use and glitchy in Qt Designer. I couldn't resize them, they often resized themselves to inappropriate dimensions, and they didn't survive save/load very reliably. Since I often found myself having to edit the XML output of Designer and reload, I switched to absolute positioning. Due to the fixed-size screen on the product the interface is for, this is acceptable.

anda_skoa
30th May 2019, 10:43
I couldn't figure out how to shift the slider to one side or the other, so I just made the slider wider than it needed to be and buried the unwanted space under some buttons to the side.

Shifting the slider might be possible with a stylesheet but it should definitely work with a custom style.



Proper layouts are both hard to use and glitchy in Qt Designer.

In Designer they require a bit of getting used to but they work very nicely in code.


Due to the fixed-size screen on the product the interface is for, this is acceptable.

Ah. And not needing translations either?

In any case your type of UI looks like it would be much more a candidate for using QtQuick instead of QtWidgets.

Cheers,
_

DDR
4th June 2019, 02:19
And not needing translations either?

I think we should be able to do that with Widgets, shouldn't we? It seems to have a patina of translation stuff built around it.



In any case your type of UI looks like it would be much more a candidate for using QtQuick instead of QtWidgets.

In our testing, our target CPU wasn't powerful enough to run QtQuick at a reasonable framerate. We don't have a functional GPU, so we're relying on slow software rendering to the framebuffer. So, while I'd love to… it's among the many things I can't have.
Also, does QtQuick have a visual layout tool like Designer?

Thanks,
–DDR

anda_skoa
7th June 2019, 09:40
I think we should be able to do that with Widgets, shouldn't we?

Of course.

I was just asking because you say you have fixed sizes.
The moment you have translations that is no longer true.




In our testing, our target CPU wasn't powerful enough to run QtQuick at a reasonable framerate. We don't have a functional GPU, so we're relying on slow software rendering to the framebuffer.

Is that with the QQuick 2D render (https://doc.qt.io/QtQuick2DRenderer/) or using software rendered OpenGL?

The former was specifically created for systems without GPU.
There is even a research project for running QtQuick UIs on micro controllers (https://blog.qt.io/blog/2018/05/03/qt-microncontrollers-mcu/)



Also, does QtQuick have a visual layout tool like Designer?


There is a visual designer, however most people prefer to do the layouting in QtQuick manually. Either suing anchors or the layout types.

Cheers,
_