[PySide] Problem with garbage collection

henry.wede at yahoo.com henry.wede at yahoo.com
Thu Feb 9 21:54:35 CET 2023


 Hello,
I think that I have a solution... it seems like the clear method of the listwidget was the problem.  Here is what I tried.
Last night I taught each of the objects how to save themselves as XML and recreate themselves from XML.  Buttons were added to load & save the "project".  Now the program loads the XML and several Python lists of objects (subclasses from QTreeWidgetItem) are created and displayed in a TreeViewWidget.  When the user clicks on one of the lists in a TreeViewWidget, the objects in the Python list are displayed in the ListWidget for editing.  So far, so good.
This is where it gets strange.  For testing, I disabled the methods for updating the Python lists.  The objects are ~just~ created from XML.  When I display those items using the ListWidget .addItem() method they display correctly.  But only the first time!  If I clear the list and display the same objects in the same list a second time then I get the error.  So it seems that the addItem method "takes control" of the object in the Python list and the clear() method destroys the internal object - even though I can print the objects in the Python list so they seem to still exist.  They are like zombies without a C++ soul :)
Then I tried using the copy module to add a copy of the object to the ListWidget instead of the real object - but it has an error that the copy module cannot copy the item because it cannot pickle it.
Lastly, I eliminated the trouble-causing clear() method completely and now "remove" the list items manually like this:
for N in range( ListWidget.count(), -1, -1): Whatever = ListWidget.takeItem(N)
I don't feel very professional doing it this way, but it seems to be working.
Thank you very much for your help and suggestions!  I appreciate your time.
Henry


    On Thursday, February 9, 2023 at 12:24:29 AM MST, Boštjan Mejak <bostjan.xperia at gmail.com> wrote:  
 
 So, you tried creating a separate list (like in my example) and it still doesn’t work? You still get the exact same error as before?
On Thu, 9 Feb 2023 at 03:29 henry.wede at yahoo.com <henry.wede at yahoo.com> wrote:

 Hello,
Thank you for your reply.  I will have to think about the best way to make this work within the program.  I am still confused a bit.
Currently, the user has buttons and context menus to create the custom items in the list view.  This is nice for them because they can easily see the changes.  When the user is done arranging and creating items in the list widget, then the program stores the items (which are all custom objects derived from the QListWidgetItem) into a Python list for storage.  It looks like this:
for N in range( ListWidget.count() ): self.Positions.append( ListWidget.item(N) )
Then the list widget is cleared after the items are stored to a Python list.
But - if I print the items from the Python list they are all still there as expected.  If I look at the type() of the items in the list they are all the custom types (also as expected).  But if the program takes an item from the Python list and adds it to the list widget I get the error.  It seems that the objects were stored correctly, but obviously not completely.
So the items are stored before the list widget is cleared - I think this is what you were showing in your example.  But it is done "at the end" instead of right away.  I still feel that I am doing something else wrong.

Henry

    On Wednesday, February 8, 2023 at 05:16:03 PM MST, Boštjan Mejak <bostjan.xperia at gmail.com> wrote:  
 
 Hello, Henry,
let me brighten your day, if I may.
It seems that the issue lies in the fact that you are trying to add an object to the list widget after it has already been deleted. When the list widget is cleared using the .clear() method, the objects contained in the list are deleted, which means that any references to those objects will no longer be valid.

To avoid this issue, you can store the data in a separate list and add the items to the list widget after it has been cleared. For example, you could define a positions list and store the RobotPosition objects in it, then clear the list widget and add the items from the positions list.
Let me give you an example.
---positions = []

Position = ConfigurationClasses.RobotPosition()
Position.setType('Intermediate')
Position.setName('Position')
Position.updateTooltip()

positions.append(Position)
self.ui.listRobotPathPositions.clear()

for position in positions:
    self.ui.listRobotPathPositions.addItem(position)---
This way, the objects will not be deleted until the positions list goes out of scope, or is explicitly deleted. I hope this solves your problem.


On Thu, Feb 9, 2023 at 12:53 AM henry.wede--- via PySide <pyside at qt-project.org> wrote:

Hello,
I am trying to track down a " Internal C++ object (RobotPosition) already deleted" error.  The Internet says that my object is being garbage collected because it falls out of scope.  This is part of a big application so I can't just post a folder of code, but please let me try to explain what I think the problem is.
I have an object that is defined like this:
class RobotPosition(QtWidgets.QListWidgetItem):    '''Class for storing a single robot position.    '''
    def __init__(self):
 super().__init__()
        {snip}

    def __str__(self):
                {snip}
    def setType(self, Type):
                {snip}
    def setName(self, NewName):
                {snip}
    def updateTooltip(self):
                {snip}
Theses objects are created (as shown below) and added to a list widget. 
{snip}Position = ConfigurationClasses.RobotPosition()Position.setType('Intermediate')Position.setName('Position')Position.updateTooltip()

self.ui.listRobotPathPositions.addItem(Position)print(Position.parent()) 
{snip}
The objects display without any issues with the addItem method of the list widget.
The application stores different lists of these objects and uses the same list widget to display them.  If I print these list of objects, they all print nicely due to the __str__ method.  So far, so good.
But when the list widget is cleared (using .clear() ) and the application tries to add a list of objects back to the list widget this message shows up:Internal C++ object (RobotPosition) already deleted

I added the 'print(Position.parent()) ' command above and it says that:AttributeError: 'RobotPosition' object has no attribute 'parent'

So... I think this is the heart of my problem.  Python ( or Qt?) thinks my RobotPosition object has no parent.  However, I think that it does have a parent because it is derived from a QListWidgetItem object that has a parent.  
Could someone please shed some light on what I am doing wrong?
Thanks in advance,Henry





_______________________________________________
PySide mailing list
PySide at qt-project.org
https://lists.qt-project.org/listinfo/pyside

  
  
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/pyside/attachments/20230209/7fe2fbe7/attachment-0001.htm>


More information about the PySide mailing list