QWidget inheriter in QScrollArea : problem of scroll clipping
-
Dear All,
I am quite new to QT5 / QT5 for Python (here on Linux). I created in inheriter of QWidget which is placed inside a QScrollArea. In ma QWidget, I override the paintEvent an I draw stuff inside. It works well, and the things I paint follow the scrollbars. Good.
Now I want to draw an "overlay" element, which position does not follow the scrollbars (it is "fixed" even when I move the scrollbars). About the coordinates system, I played successfully I guess withmapFromParent to get the good coordinates. And it works but I need to resize the window (for example) to obtain the good result. If I only play with the scrollbars, I have only a part of the element that is painted, and sometimes it disappears too.I think I have a problem with the clipping, but I did not understand what I should do to put the full viewport area as clipping area (or perhaps is there a better way to do this ?).
Can someone help ?
Thanks a lot,
Mike -
Hi,
Without any code, it's hard to tell. Would it be possible to see it ?
Depending on what you want to do, you might want to check the Graphics View Framework.
-
Sorry for the delay I was not notified about your kind message.
I wrote a simplified code that exhibits the same problem. First I made a global UI design in "designer". The part that intersts us is pictured here :
Then I wrote a "MImage.py" file that contains the following code (simplified a lot but working example) :from PyQt5 import QtWidgets, QtCore, uic, QtGui class MImage(QtWidgets.QWidget): def __init__(self, *arg): super().__init__() self.image = QtGui.QImage("path_to_some_picture_here..jpg") self.MRedBrush = QtGui.QBrush(QtGui.QColor(200,0,0)) def paintEvent(self, event): self.resize(self.image.width(), self.image.height()) # below : not sure to understand why I need the parent of the parent widget, it is not similar as in Designer. self.parentWidget().parentWidget().setHorizontalScrollBarPolicy( QtCore.Qt.ScrollBarAsNeeded ) self.parentWidget().parentWidget().setVerticalScrollBarPolicy( QtCore.Qt.ScrollBarAsNeeded ) painter = QtGui.QPainter(self) # draw some scrollable stuff pixMap = QtGui.QPixmap.fromImage(self.appData.image) painter.drawPixmap(QtCore.QRect(0, 0, self.image.width(), self.image.height()), pixMap) # draw some non scrollable stuff << == here is the problem topleft=self.mapFromParent(QtCore.QPoint(20,20)) painter.fillRect(topleft.x(),topleft.y(),500,20,self.MRedBrush)
When I do this, I get this :
---> At program startup :
---> After a horizontal scroll :
---> After resizing a bit the window to force an repaint :
So it seems my code is correct regarding the drawing coordinates. However, during the scroll, it seems a full repaint is not performed. I guess it is due to clipping rectangle (I guess Qt uses hardware acceleration to bitmap copy the contents of a part of the view). So my question is : is there a way to enforce the clipping rectangle to the whole view for example (or to exclude the part that interests me from the clipping region), or is there a better design for this (perhaps superimposing two views, one for scroll, another one for static display).
Thanks a lot,
Mikhaël -
Why are you calling resize in your paintEvent ?
Accessing the parent of the parent is a bad idea and even more in the paintEvent. Accessing parent is already a bad idea.
Since that rectangle shall not move, why not put it in its own widget that you manually place at that fixed position ?
-
I am not a skilled user and I don't know how to add a widget superimposed to another one. Can you give some advice about it ?
I however found a solution. My interpretation was not correct, clipping does not seems to come from system areas to update. So what I did was the following : let's call scrollerwidget the scrollarea, I added an update to the event related to scrollers position change :
self.scrollerWidget.horizontalScrollBar().valueChanged.connect(self.update)
self.scrollerWidget.verticalScrollBar().valueChanged.connect(self.update)It works. But I would like to know, as you suggest, how to add another widget superimposed ?
Thanks a lot,
Mike -
I am not a skilled user and I don't know how to add a widget superimposed to another one. Can you give some advice about it ?
I however found a solution. My interpretation was not correct, clipping does not seems to come from system areas to update. So what I did was the following : let's call scrollerwidget the scrollarea, I added an update to the event related to scrollers position change :
self.scrollerWidget.horizontalScrollBar().valueChanged.connect(self.update)
self.scrollerWidget.verticalScrollBar().valueChanged.connect(self.update)It works. But I would like to know, as you suggest, how to add another widget superimposed ?
Thanks a lot,
Mike@Mika-L said in QWidget inheriter in QScrollArea : problem of scroll clipping:
how to add another widget superimposed ?
To add a fixed widget above the scroll area, create a new widget with the scroll area (image_area_scroller) as parent.
It will be at fixed position on the left top corner of the scroll area, regardless the scroll bars.