[prev in list] [next in list] [prev in thread] [next in thread] 

List:       pykde
Subject:    Painting artifacts with drawForeground in a QGraphicsView with no frame shape
From:       Maurizio Berti <maurizio.berti () gmail ! com>
Date:       2020-11-16 16:14:51
Message-ID: CAPn+-XSy_LGjtedRrdf8v8vHoZdiF5R=898ss5A-vYxU+Uk80g () mail ! gmail ! com
[Download RAW message or body]

[Attachment #2 (multipart/alternative)]


I need to paint some static content on a QGraphicsView with
drawForeground().

Unfortunately, it seems that unsetting the frame shape with
setFrameShape(NoFrame) creates some painting artifacts, as the drawn
contents get "buffered" and follow the scene contents when scrolling.

I'm attaching two images to demonstrate it. The first (scrollwork.png) is
the expected result, while the second (scrollbug.png) shows what happens
when scrolling.

Note that as soon as the widget is *fully* repainted (by changing screen,
resizing, unminimizing, unfocusing, etc) the painting is correct again.
Changing the style doesn't solve the problem.

It seems that this can be avoided by setting the stylesheet with
`QGraphicsView {border: none;}`, but I'd like to understand the following:

1. Is this a (known) bug? Is it (as I believe) a Qt bug or PyQt one?
2. Is there something that can be done to prevent this from happening,
except calling update() on the whole viewport everytime the view is
scrolled (which is what I believe is happening when using the stylesheet,
and I'm afraid it theoretically affects performance, which is very
important for this project)?

I can confirm the bug on Linux with PyQt 5.7 and 5.12.

The following is a simple example to reproduce it:

from PyQt5 import QtCore, QtGui, QtWidgets
from random import randrange

class Test(QtWidgets.QGraphicsView):
    def __init__(self):
        super().__init__()
        scene = QtWidgets.QGraphicsScene()
        self.setScene(scene)
        for r in range(10):
            r = scene.addRect(randrange(1000), randrange(1000),
                randrange(1000), randrange(1000))
            r.setBrush(QtGui.QColor(QtCore.Qt.GlobalColor(randrange(19))))
        self.setFrameShape(0)
        self.viewport().setObjectName('viewport')
        self.setStyleSheet('Test {border: none;}')

    def drawForeground(self, qp, rect):
        qp.save()
        qp.resetTransform()
        qp.setBrush(QtGui.QColor('orange'))
        rect = QtCore.QRect(20, 20, 100, 30)
        qp.drawRect(rect)
        qp.drawText(rect, QtCore.Qt.AlignCenter, 'Test')
        qp.restore()

import sys
app = QtWidgets.QApplication(sys.argv)
w = Test()
w.show()
sys.exit(app.exec_())

Thanks,
Maurizio
-- 
È difficile avere una convinzione precisa quando si parla delle ragioni del
cuore. - "Sostiene Pereira", Antonio Tabucchi
http://www.jidesk.net

[Attachment #5 (text/html)]

<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div>I need to paint some \
static content on a QGraphicsView with \
drawForeground().</div><div><br></div><div>Unfortunately, it seems that unsetting the \
frame shape with setFrameShape(NoFrame) creates some painting artifacts, as the drawn \
contents get &quot;buffered&quot; and follow the scene contents when \
scrolling.</div><div><br></div><div>I&#39;m attaching two images to demonstrate it. \
The first (scrollwork.png) is the expected result, while the second (scrollbug.png) \
shows what happens when scrolling.</div><div><br></div><div><div>Note that as soon as \
the widget is *fully* repainted (by changing screen, resizing, unminimizing, \
unfocusing, etc) the painting is correct again. Changing the style doesn&#39;t solve \
the problem.</div><div><br></div><div>It seems that this can be avoided by setting \
the stylesheet with `QGraphicsView {border: none;}`, but I&#39;d like to understand \
the following:</div></div><div><br></div><div>1. Is this a (known) bug? Is it (as I \
believe) a Qt bug or PyQt one?</div><div>2. Is there something that can be done to \
prevent this from happening, except calling update() on the whole viewport everytime \
the view is scrolled (which is what I believe is happening when using the stylesheet, \
and I&#39;m afraid it theoretically affects performance, which is very important for \
this project)?</div><div><br></div><div>I can confirm the bug on Linux with PyQt 5.7 \
and 5.12.</div><div><br></div><div>The following is a simple example to reproduce \
it:</div><div><br></div><div><div><font face="monospace">from PyQt5 import QtCore, \
QtGui, QtWidgets</font></div><div><font face="monospace">from random import \
randrange</font></div><div><font face="monospace"><br></font></div><div><font \
face="monospace">class Test(QtWidgets.QGraphicsView):</font></div><div><font \
face="monospace">      def __init__(self):</font></div><div><font face="monospace">   \
super().__init__()</font></div><div><font face="monospace">            scene = \
QtWidgets.QGraphicsScene()</font></div><div><font face="monospace">            \
self.setScene(scene)</font></div><div><font face="monospace">            for r in \
range(10):</font></div><div><font face="monospace">                  r = \
scene.addRect(randrange(1000), randrange(1000),  </font></div><div><font \
face="monospace">                        randrange(1000), \
randrange(1000))</font></div><div><font face="monospace">                  \
r.setBrush(QtGui.QColor(QtCore.Qt.GlobalColor(randrange(19))))</font></div><div><font \
face="monospace">            self.setFrameShape(0)</font></div><div><font \
face="monospace">            \
self.viewport().setObjectName(&#39;viewport&#39;)</font></div><div><font \
face="monospace">            self.setStyleSheet(&#39;Test {border: \
none;}&#39;)</font></div><div><font face="monospace"><br></font></div><div><font \
face="monospace">      def drawForeground(self, qp, rect):</font></div><div><font \
face="monospace">            qp.save()</font></div><div><font face="monospace">       \
qp.resetTransform()</font></div><div><font face="monospace">            \
qp.setBrush(QtGui.QColor(&#39;orange&#39;))</font></div><div><font face="monospace">  \
rect = QtCore.QRect(20, 20, 100, 30)</font></div><div><font face="monospace">         \
qp.drawRect(rect)</font></div><div><font face="monospace">            \
qp.drawText(rect, QtCore.Qt.AlignCenter, &#39;Test&#39;)</font></div><div><font \
face="monospace">            qp.restore()</font></div><div><font \
face="monospace"><br></font></div><div><font face="monospace">import \
sys</font></div><div><font face="monospace">app = \
QtWidgets.QApplication(sys.argv)</font></div><div><font face="monospace">w = \
Test()</font></div><div><font face="monospace">w.show()</font></div><div><font \
face="monospace">sys.exit(app.exec_())</font></div></div><div><br></div><div>Thanks,</div><div>Maurizio</div>-- \
<br><div dir="ltr" class="gmail_signature">È difficile avere una convinzione precisa \
quando si parla delle ragioni del cuore. - &quot;Sostiene Pereira&quot;, Antonio \
Tabucchi<br><a href="http://www.jidesk.net" \
target="_blank">http://www.jidesk.net</a></div></div></div></div></div>


["scrollwork.png" (image/png)]
["scrollbug.png" (image/png)]

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic