Re: [PySide] Problem with garbage collection

2023-02-09 Thread David Ching
>from: "henry.w...@yahoo.com  " 
>mailto:henry.w...@yahoo.com> >

> 

>Thanks for looking that up.  It knew learning C++ would make me a better 
>Python programmer :)

> Seems too hard though...

 

Sure, I learned Qt with C++ and only recently switched to Python for the dev 
productivity.  Glad my background is useful.  

 

>My method probably does seem strange, but I will try to explain it.

> I have to store a bunch of lists containing both commands and robot positions.

> I made different objects to store the items information because it keeps 
> things organized.

> […]

> Then I thought that I would be clever... since I am making objects anyway, 
> why not derive

> those objects from a QListWidgetItem?  Then when I need to display the 
> objects I can just

> add them to a list widget and the displaying is done in only a couple lines 
> of code.  Also, the

> program can change the icons or text color with just a couple lines.  But I 
> only use one list

> widget to display the all of the lists - one at a time, of course.  The list 
> widget is reused/recycled.

> 

>That is why I am putting things into a list widget, moving them around, 
>storing them,

> clearing the list widget and doing it again.

> Probably not what the folks at Qt thought I was going to do.

 

Have you considered using a QListView instead of a QListWidget?  I believe that 
allows you to save your robot objects, etc. in a plain data object, and then 
display them in the same list display as QListWidget.  I do believe QListWidget 
is much easier, though and wonder if the model/view architecture is worth the 
increased complexity for your case.  But in any case, I think that is how the 
folks at Qt provided for what you are trying to do.

 

Thanks,

David

___
PySide mailing list
PySide@qt-project.org
https://lists.qt-project.org/listinfo/pyside


Re: [PySide] Problem with garbage collection

2023-02-09 Thread henry.wede--- via PySide
 David,
Thanks for looking that up.  It knew learning C++ would make me a better Python 
programmer :)  Seems too hard though...
My method probably does seem strange, but I will try to explain it.  I have to 
store a bunch of lists containing both commands and robot positions.  I made 
different objects to store the items information because it keeps things 
organized.  It is easy to access Position.CoordinateSystem and things like 
that.  The program has many list of these objects.  
Then I thought that I would be clever... since I am making objects anyway, why 
not derive those objects from a QListWidgetItem?  Then when I need to display 
the objects I can just add them to a list widget and the displaying is done in 
only a couple lines of code.  Also, the program can change the icons or text 
color with just a couple lines.  But I only use one list widget to display the 
all of the lists - one at a time, of course.  The list widget is 
reused/recycled.
That is why I am putting things into a list widget, moving them around, storing 
them, clearing the list widget and doing it again.Probably not what the folks 
at Qt thought I was going to do.
Henry

On Thursday, February 9, 2023 at 02:55:39 PM MST, David Ching 
 wrote:  
 
 >from: "henry.w...@yahoo.com" 

Henry> it seems like the clear method of the listwidget was the problem.?
Here is what I tried.
[...]
 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 :) 
[...]
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.

The C++ code for QListWidget::clear() is as follows.  

 1: // NOTE:  QListWidget::clear() calls QListModel::clear()
 2: void QListModel::clear()
 3: {
 4:    beginResetModel();
 5:    for (int i = 0; i < items.count(); ++i) {
 6:        if (items.at(i)) {
 7:            items.at(i)->d->theid = -1;
 8:            items.at(i)->view = nullptr;
 9:            delete items.at(i); 
10:        }
11:    }
12:    items.clear();
13:    endResetModel();
14: }


So yes, on line 9, the QListWidgetItem C++ object is deleted (so it's
"soul") is indeed destroyed!  This is printed in red at
https://doc.qt.io/qt-6/qlistwidget.html#items:  "Warning: All items will be
permanently deleted."

Why do you need to access the QListWidgetItem after you clear it from the
list?  Perhaps you should create new QListWidgetItem's and call
QListWidget.addItem() for those new instances instead.  

Or just use QListWidget.takeItem() as you have done.  Nothing wrong with
that.  

I have also found QListWidgetItem.setHidden() to be great as it lets me keep
the item in the list but the user has no knowledge.

Good luck,
David 




  ___
PySide mailing list
PySide@qt-project.org
https://lists.qt-project.org/listinfo/pyside


Re: [PySide] Problem with garbage collection

2023-02-09 Thread David Ching
>from: "henry.w...@yahoo.com" 

Henry> it seems like the clear method of the listwidget was the problem.?
Here is what I tried.
[...]
 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 :) 
[...]
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.

The C++ code for QListWidget::clear() is as follows.  

 1: // NOTE:  QListWidget::clear() calls QListModel::clear()
 2: void QListModel::clear()
 3: {
 4: beginResetModel();
 5: for (int i = 0; i < items.count(); ++i) {
 6: if (items.at(i)) {
 7: items.at(i)->d->theid = -1;
 8: items.at(i)->view = nullptr;
 9: delete items.at(i); 
10: }
11: }
12: items.clear();
13: endResetModel();
14: }


So yes, on line 9, the QListWidgetItem C++ object is deleted (so it's
"soul") is indeed destroyed!  This is printed in red at
https://doc.qt.io/qt-6/qlistwidget.html#items:  "Warning: All items will be
permanently deleted."

Why do you need to access the QListWidgetItem after you clear it from the
list?  Perhaps you should create new QListWidgetItem's and call
QListWidget.addItem() for those new instances instead.  

Or just use QListWidget.takeItem() as you have done.  Nothing wrong with
that.  

I have also found QListWidgetItem.setHidden() to be great as it lets me keep
the item in the list but the user has no knowledge.

Good luck,
David 




___
PySide mailing list
PySide@qt-project.org
https://lists.qt-project.org/listinfo/pyside


Re: [PySide] Problem with garbage collection

2023-02-09 Thread henry.wede--- via PySide
 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 
 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.w...@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 
 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 
 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 

Re: [PySide] Problem with garbage collection

2023-02-08 Thread henry.wede--- via PySide
 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 
 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 
 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@qt-project.org
https://lists.qt-project.org/listinfo/pyside

  ___
PySide mailing list
PySide@qt-project.org
https://lists.qt-project.org/listinfo/pyside


[PySide] Problem with garbage collection

2023-02-08 Thread henry.wede--- via PySide
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@qt-project.org
https://lists.qt-project.org/listinfo/pyside