[Interest] QGraphicsView selection not honoring QGraphicsItem::shape?

Christian Gagneraud chgans at gmail.com
Mon Jun 26 05:17:40 CEST 2017

On 26 June 2017 at 14:57, Patrick Stinson <patrickkidd at gmail.com> wrote:
> Thanks for the important tips, I wasn’t aware of any of them! I implemented
> all of them.
> Unfortunately it is still selecting based on boundingRect. Any other
> thoughts?

Then the path returned by your shape() is wrong, first of all shape()
should return a shape, not a simple path.
You need to use QPainterPathStoker, to stroke your path with a width
equal to the one of the pen used to paint your item.

def shape():
 stroker = QPainterPathStroker()
 return stroker.stroke(self.path)

def paint():
  # Debug
  painter.setPen(QPen(Qt::red, Qt::DotLine, 0.0))
  painter.setPen(QPen(Qt::blue, Qt::DotLine, 0.0))

self.path should be a simple path (a line string, aka open multiline)
connecting the two item.
then you stroke this path in your shape() function, and you draw it in
your paint function.

For debug purpose, you might want to paint the result of shape() in
your paint function.

You can also use qammaray for this sort of troubleshooting.

If things still don't work, please post your code, and the output of:
qDebug() << item.pos() << item.boundingRect() << item.shape();

Good luck!


> On Jun 25, 2017, at 5:00 PM, Christian Gagneraud <chgans at gmail.com> wrote:
> On 26 June 2017 at 05:10, Patrick Stinson <patrickkidd at gmail.com> wrote:
> Hi there!
> I have a simple QGraphicsItem which draws the left, bottom, and right
> borders of it’s bounding rect. I am painting the item by creating a
> QGraphicsPath from top-left => bottom-left => bottom-right =>? top-right.
> I have reimplemented shape() to return this path, but the view is still
> using the item’s bounding rect to select. I have tested this by dragging my
> selection marquee down through the top border of the item. I tried
> re-tracing the QPainterPath back to the beginning in case it was
> automatically closing it from top-right to top-left, but it didn’t help.
> Is there something else that needs to happen to get the view to honor
> shape()?
> See code and screenshot below.
> Thanks!
> -Patrick
> class Marriage(QGraphicsItem, util.Debug):
>    def __init__(self, a, b):
>        super().__init__()
>        global last_id
>        self.id = last_id = last_id + 1
>        self.setFlag(QGraphicsItem.ItemIsSelectable, True)
>        self.path = QPainterPath()
>        self.pen = util.PEN
>        self.people = [a, b]
>        self.children = []
>        self.hover = False # highlight
>        self.update()
>    def boundingRect(self):
>        return self.shape().boundingRect()
>    def shape(self):
>        return self.path
>    def update(self, *args):
> BTW, update() is not a virtual method, you should instead implement a
> custom function, say updateShape() in which you first call
> prepareGeometryChange(). No need to call update().
> Chris

More information about the Interest mailing list