Search code examples
pythonpyqtpyqt5qgraphicsscene

How to remove QRect from QGraphicsScene


I have a QGraphicsScene with a bunch of QRects. I'm using the QRects as an overlay over a QPixmap to show detected object. I need to clear all the rectangles from the scene, but can't figure out how.

What is the best way to clear all of the QRects from the QGraphicsScene without redrawing the image?

Right now I'm keeping a list of QRects as I add them to the scene and then to clear I try to loop through all the rects and use QGraphicsScene.removeItem(rect) to remove the rectangle, but that doesn't work. I get the following error:

TypeError: removeItem(self, QGraphicsItem): argument 1 has unexpected type 'QRectF'

I guess a QRect isn't a graphics item. But how should I remove it from the scene. Below is the code where I add or (try to) remove the Rects:

if self.is_viewing_tracks:
    for track_id, positions in self.tracks.items():
        for frameno, pos in positions.items():
            if int(frameno) == self.frameno:
                x, y = pos
                rect = QRectF(x-5, y-5, 10, 10)
                self.scene.addRect(rect)
                text = self.scene.addText(str(track_id))
                text.setPos(x, y)
                self.rects.append(rect)
            else:
                for rect in self.rects:
                    self.scene.removeItem(rect)

What is the right way to remove QRects from a QGraphicsScene?


Solution

  • QRectFs are not added to the QGraphicsScene but are used to create QGraphicsRectItem through the addRect() method, so you must remove the QGraphicsRectItem and not the QRectF. The solution is to store the QGraphicsRectItems in self.rects:

    if self.is_viewing_tracks:
        for track_id, positions in self.tracks.items():
            for frameno, pos in positions.items():
                if int(frameno) == self.frameno:
                    x, y = pos
                    rect = QRectF(x - 5, y - 5, 10, 10)
                    rect_item = self.scene.addRect(rect)
                    text = self.scene.addText(str(track_id))
                    text.setPos(x, y)
                    self.rects.append(rect_item)
                else:
                    for rect in self.rects:
                        self.scene.removeItem(rect)
                    self.rects = []