QGraphicsItems ZValue and detection priority



  • Hey guys,

    I have 2 QGraphicsItems,
    1 with a rect (0, 0, 200, 50) (this one has nothing painted in it)
    2nd one parented under the first one with a rect (0, 0, 200, 200) (this one has a background)

    I am setting the 2nd with a ZValue of -1 so it's displayed behind the parent.

    When I try to find the item at a click position, it always detects the 2nd one that is supposed to be behind the first one. How is that possible ??? the one with the highest ZValue should be detected first.

    Any idea ?

    Thx



  • Hi @Goffer
    Since the default z value for a graphics item os 0 perhaps -1 is not a good value for this?? I never use -1 for this always greater than 0.
    If you have made your own subclass of graphics items make sure your bounding box return value is correct.
    I assume you have made the item selectable right?
    Other than that I am not sure what the problem might be.



  • Hey @kenchan

    I ve tried 0 and 1 too but it's the same.
    Actually the main item is selectable and the child is not (since that's the behavior I need) but it always returns the child that is behind ...

    EDIT
    So, somehow the child item doesn't go behind even by setting the ZValue, here is a bit of code that represents what I am trying to do.

    from PySide2 import QtWidgets, QtGui, QtCore
    
    class View(QtWidgets.QGraphicsView):
    
        def __init__(self, parent):
            super(View, self).__init__(parent)
    
        def mousePressEvent(self, event):
    
            itemAtPos = self.scene().itemAt(self.mapToScene(event.pos()), QtGui.QTransform())
            print itemAtPos
    
            super(View, self).mousePressEvent(event)
    
    class Item1(QtWidgets.QGraphicsItem):
    
        def __init__(self, parent):
            super(Item1, self).__init__(parent)
    
            self.setAcceptHoverEvents(True)
            self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable)
            self.setFlag(QtWidgets.QGraphicsItem.ItemIsSelectable)
    
        def boundingRect(self):
            """
            The bounding rect based on the width and height variables.
    
            """
            rect = QtCore.QRectF(QtCore.QRect(0, 0, 200, 50))
            return rect
    
        def shape(self):
            """
            The shape of the Slot is a circle.
    
            """
            path = QtGui.QPainterPath()
            path.addRect(self.boundingRect())
            return path
    
        def paint(self, painter, option, widget):
            """
            Paint the item.
    
            """
            self._brush = QtGui.QBrush()
            self._brush.setStyle(QtCore.Qt.SolidPattern)
            self._brush.setColor(QtGui.QColor(200,200,200,255))
           
            painter.setBrush(self._brush)
            painter.drawRect(self.boundingRect())
    
    
    class Item2(QtWidgets.QGraphicsItem):
    
        def __init__(self, parent):
            super(Item2, self).__init__(parent)
    
        def boundingRect(self):
            """
            The bounding rect based on the width and height variables.
    
            """
            rect = QtCore.QRectF(QtCore.QRect(0, 0, 200, 500))
            return rect
    
        def shape(self):
            """
            The shape of the Slot is a circle.
    
            """
            path = QtGui.QPainterPath()
            path.addRect(self.boundingRect())
            return path
    
        def paint(self, painter, option, widget):
            """
            Paint the item.
    
            """
            self._brush = QtGui.QBrush()
            self._brush.setStyle(QtCore.Qt.SolidPattern)
            self._brush.setColor(QtGui.QColor(200,0,0,255))
           
            painter.setBrush(self._brush)
            painter.drawRect(self.boundingRect())
    
    
    v = View(parent=None)
    s = QtWidgets.QGraphicsScene()
    v.setScene(s)
    
    i1 = Item1(parent=None)
    i1.setZValue(1)
    
    i2 = Item2(parent=i1)
    i2.setZValue(0)
    
    s.addItem(i1)
    
    v.show()
    
    


  • I don't use PySide so I cannot offer much help on this one.
    I have possibly dumb question though. Don't you need to add i2 to the scene as wall as i1, like s.addItem(i2)??
    If this was c++ you would have to do that.



  • Nope,
    since you specify it's a child of i1 and i1 is already in the scene.
    And it's being displayed in the view so it should be fine (If i had to add it , I wouldn't see it in the view). I've never had to add my children items to the scene.

    (I've tried to add it just in case but it doesn't change anything)
    Could you try to do that in C++ and see if it works ?



  • @Goffer
    I tried it in c++ and I got similar behaviour until i set the QGraphicsItem::ItemStacksBehindParent flag to true on item 2. Then i was able to select either item 1 or item 2 by clicking on each item.



  • @kenchan said in QGraphicsItems ZValue and detection priority:

    ItemStacksBehindParent

    Ohhhhh, I didn't know about that one !! But that's a bit confusing that it's not possible just by using the Zvalue as it seems to be designed for that purpose ...

    Anyway, I gave it a try and it works.

    Thank you !



  • Yes, I am not sure what is going on with the zvalue in this case.
    Glad it to hear it works for you now though.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.