Search code examples
pythonpyqtpyqt5qgraphicsitem

How to delete a QGraphicsItem in Pyqt5


I am trying to find out how to delete a QGraphicsItem using python. Currently, I am using scene.removeItem(item) to remove the item from a QGraphicsScene. However, does that delete the item as well (from memory)?

If not, is there a way to do so? Will the del keyword accomplish this? Sorry, I'm fairly new to this so I would appreciate any advice/feedback.


Solution

  • When adding an item to the scene the one that manages the memory of the item is no longer python but the scene but when you use removeItem() does not remove it from memory but returns ownership of the item to python, and in that case python remove it when deemed necessary, to verify I have created a simple example:

    from PyQt5 import QtCore, QtWidgets
    
    
    class GraphicsRectItem(QtWidgets.QGraphicsRectItem):
        def __del__(self):
            print("deleted")
    
    
    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self, parent=None):
            super().__init__(parent=parent)
    
            self.scene = QtWidgets.QGraphicsScene()
            self.view = QtWidgets.QGraphicsView(self.scene)
            self.setCentralWidget(self.view)
    
            item = GraphicsRectItem(10, 10, 100, 100)
            self.scene.addItem(item)
    
            QtCore.QTimer.singleShot(1000, lambda: self.scene.removeItem(item))
    
    
    def main():
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
    
        mytable = MainWindow()
        mytable.show()
        sys.exit(app.exec_())
    
    
    if __name__ == "__main__":
        main()
    

    If you want to explicitly remove from memory the C++ object (not the python object) then you can use sip:

    from PyQt5.QtWidgets import QGraphicsScene
    # sip should be imported after pyqt5
    import sip
    # ...
    scene.removeItem(item)
    sip.delete(item)