Treectrl ItemId drag-drop

J Ellianef wrote:

Hello,
Thanks for your previous explanations.
Now I 'm trying to implement drag and drop and have problems with TreeItemId. If a tree is displayed and I begin dragging an item, it's ID is not always the same.
Code:
def OnBeginDrag(self, event):
   self.drag_src_item=event.GetItem()
   wx.TreeEvent.Allow(event)
   print "Drag Src item=",self.drag_src_item
   self.drag_src_data= self.GetPyData( self.drag_src_item)
and dragging 6 times the same item I get:
Drag Src item= <wx._controls.TreeItemId; proxy of C++ wxTreeItemId instance at _78a86f01_p_wxTreeItemId>
Drag Src item= <wx._controls.TreeItemId; proxy of C++ wxTreeItemId instance at _e8a86f01_p_wxTreeItemId>
Drag Src item= <wx._controls.TreeItemId; proxy of C++ wxTreeItemId instance at _d0a66f01_p_wxTreeItemId>
Drag Src item= <wx._controls.TreeItemId; proxy of C++ wxTreeItemId instance at _78a86f01_p_wxTreeItemId>
Drag Src item= <wx._controls.TreeItemId; proxy of C++ wxTreeItemId instance at _e8a86f01_p_wxTreeItemId>
Drag Src item= <wx._controls.TreeItemId; proxy of C++ wxTreeItemId instance at _d0a66f01_p_wxTreeItemId>
The instance is quite random, and is ennoying for collapseAndReset and Expand the parent to update the tree view after drag-drop.

The C++ wxTreeItemId is just an "opaque" data structure that abstracts the concept of a handle to an item in the tree, so it's the hidden guts of the wxTreeItemId that matter, not the wxTreeItemId itself. (In fact since it is such a cheap operation the guts are copied to new instances often, such as every time one is returned from a method, etc. That allows the internal code to be simpler and not have to worry about dynamic allocation, ref-counting, etc. )

The Python wrapper for wxTreeItemId is just a proxy for the C++ class, and again, new instances of the proxy may be created as needed, even for the same instance of the the C++ object. However there is an equality operator that should tell you if the two items refer to the same node in the tree, for example:

  if currentItem == self.oldItem:
    ...

Alternately, is it possible to retrieve an ItemId from it's data since the PyData is always correct?

In most cases you should assume that the wx.TreeItemId objects are transitory, IOW they can come and go as needed. The main exception to this is the root node, which, unless you remove and add a new root, will always contain the handle for the root. If you need to have some sort of unique ID for the items then put it in your PyData, but I don't think I would store the wx.TreeItemId there because the internal handles could possibly change as other items are added or deleted. Instead you could just use the wx.TreeItemId's to respond to tree events, navigate to parent, child or sibling nodes, etc., and then use the attached PyData for everything else.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Many thanks Robin,
But I get a stange behavior: I can drag-drop files and all work quite well except when dragging from a parent node to it's child. I can't get the child expanded whatever I tried.(code begins on line 353 - OnEndDrag)
What am I doing wrong ?
Attached are all the necessary to test the code. Just update the hardcoding images root in albumroot global. Images are in photos.zip
Environment:
Win2k, Python 2.3.4, wx-2.5.3-msw-unicode
Thanks.

Robin Dunn wrote:

awin.py (22.3 KB)

jimages.py (46.1 KB)

photos.zip (6.66 MB)

···

J Ellianef wrote:

Hello,
Thanks for your previous explanations.
Now I 'm trying to implement drag and drop and have problems with TreeItemId. If a tree is displayed and I begin dragging an item, it's ID is not always the same.
Code:
def OnBeginDrag(self, event):
   self.drag_src_item=event.GetItem()
   wx.TreeEvent.Allow(event)
   print "Drag Src item=",self.drag_src_item
   self.drag_src_data= self.GetPyData( self.drag_src_item)
and dragging 6 times the same item I get:
Drag Src item= <wx._controls.TreeItemId; proxy of C++ wxTreeItemId instance at _78a86f01_p_wxTreeItemId>
Drag Src item= <wx._controls.TreeItemId; proxy of C++ wxTreeItemId instance at _e8a86f01_p_wxTreeItemId>
Drag Src item= <wx._controls.TreeItemId; proxy of C++ wxTreeItemId instance at _d0a66f01_p_wxTreeItemId>
Drag Src item= <wx._controls.TreeItemId; proxy of C++ wxTreeItemId instance at _78a86f01_p_wxTreeItemId>
Drag Src item= <wx._controls.TreeItemId; proxy of C++ wxTreeItemId instance at _e8a86f01_p_wxTreeItemId>
Drag Src item= <wx._controls.TreeItemId; proxy of C++ wxTreeItemId instance at _d0a66f01_p_wxTreeItemId>
The instance is quite random, and is ennoying for collapseAndReset and Expand the parent to update the tree view after drag-drop.

The C++ wxTreeItemId is just an "opaque" data structure that abstracts the concept of a handle to an item in the tree, so it's the hidden guts of the wxTreeItemId that matter, not the wxTreeItemId itself. (In fact since it is such a cheap operation the guts are copied to new instances often, such as every time one is returned from a method, etc. That allows the internal code to be simpler and not have to worry about dynamic allocation, ref-counting, etc. )

The Python wrapper for wxTreeItemId is just a proxy for the C++ class, and again, new instances of the proxy may be created as needed, even for the same instance of the the C++ object. However there is an equality operator that should tell you if the two items refer to the same node in the tree, for example:

    if currentItem == self.oldItem:
        ...

Alternately, is it possible to retrieve an ItemId from it's data since the PyData is always correct?

In most cases you should assume that the wx.TreeItemId objects are transitory, IOW they can come and go as needed. The main exception to this is the root node, which, unless you remove and add a new root, will always contain the handle for the root. If you need to have some sort of unique ID for the items then put it in your PyData, but I don't think I would store the wx.TreeItemId there because the internal handles could possibly change as other items are added or deleted. Instead you could just use the wx.TreeItemId's to respond to tree events, navigate to parent, child or sibling nodes, etc., and then use the attached PyData for everything else.

Roger Binns wrote:

Attached are all the necessary to test the code. Just update the hardcoding images root in albumroot global. Images are in photos.zip

Sending a 10MB attachment to thousands of mailing list members isn't
very good form :slight_smile: You should instead put the content on a web site
somewhere and just include the URL.

I still havn't received the message, so there is no way I can test it anyway. (It probably got filtered either at my MTA or my MUA.) But even if I did receive it I probably still wouldn't test it as in almost all cases I won't look at OPC (Other People's Code) that is more than 2 or three screenfuls long unless I am paid for it. Unless there is something else to draw my interest to it I just don't have the time otherwise to learn and understand the code enough to help.

Reproduce the problem in a small as possible app that does nothing else and then it's easy for other folks to look at it and to try out possible solutions. (Plus it is very likely that you will find the problem yourself in the process.)

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!