943,611 Members | Top Members by Rank

Ad:
  • Python Discussion Thread
  • Marked Solved
  • Views: 3297
  • Python RSS
Nov 24th, 2008
0

wxTreeCtrl - Load Tree structure from file

Expand Post »
Hi there. I'm writing a program that uses a tree control as a form of navigation, and the structure of the tree is set up in code as the program loads.

This is fine for now, but there is the possibility that the structure will need to expand considerably, which means I'm going to want to load it from a file (and preferably be able to save it as well, but thats not so important just now).

I need some kind of file format that will allow me to load the complete tree structure from a file. Iv messed about with this for a while, and I can load *some* items, but things go badly wrong when I have children within children and so on.

Can anyone help at all please?

Regards

Max
Reputation Points: 10
Solved Threads: 1
Light Poster
MaxVK is offline Offline
46 posts
since Nov 2008
Nov 24th, 2008
0

Re: wxTreeCtrl - Load Tree structure from file

I would suggest something like this, with the pickle module (completely untested)
python Syntax (Toggle Plain Text)
  1.  
  2. import pickle
  3.  
  4. class Tree(object):
  5. # a tree class, with a single root (a Node object)
  6. def __init__(self):
  7. self.root = None
  8. def fillCtrl(self, ctrl):
  9. # fills an empty wx.TreeCtrl (ctrl) with the content of the tree structure
  10. if self.root is None:
  11. return
  12. root_item = ctrl.AddRoot(self.root.text)
  13. self.root.fillCtrl(ctrl, root_item)
  14. def dump(self, file):
  15. # writes the tree structure to a file using the pickle protocol
  16. pickle.dump(file, self)
  17. @staticmethod
  18. def load(file):
  19. # creates a new Tree which content is read in a file
  20. return pickle.load(file)
  21. @staticmethod readCtrl(ctrl):
  22. # creates a new Tree from the content of a wx.TreeCtrl
  23. self = Tree()
  24. item = ctrl.GetRootItem()
  25. self.root = Node()
  26. self.root.text = ctrl.GetItemText(item)
  27. self.root.readCtrl(ctrl, item)
  28. return self
  29.  
  30. class Node(list):
  31. # A class for nodes of Tree objects. Each node is a list which elements are
  32. # the subnodes
  33. def __init__(self):
  34. list.__init__(self)
  35. self.text = ""
  36. def fillCtrl(self, ctrl, parent_item):
  37. # fills a wx.TreeCtrl with items corresponding to the descent of this node
  38. for child in self:
  39. item = ctrl.AppendItem(parent_item, child.text)
  40. child.fillCtrl(ctrl, item)
  41. def readCtrl(self, ctrl, item):
  42. # creates the descent of this node from the content of a wx.TreeCtrl item
  43. child_item = ctrl.GetFirstChild(item)
  44. if child_item[0]:
  45. child_item = child_item[0]
  46. else:
  47. return
  48. while True:
  49. self.append(Node())
  50. self[-1].text = ctrl.GetItemText(child_item)
  51. self[-1].readCtrl(ctrl, child_item)
  52. child_item = ctrl.GetNextSibling(child_item)
  53. if not child_item:
  54. break
  55.  
  56.  
  57. def dumpCtrl(ctrl, file):
  58. # Dumps the content of a wx.TreeCtrl to a opened file
  59. tree = Tree.readCtrl(ctrl)
  60. tree.dump(file)
  61.  
  62. def loadCtrl(ctrl, file):
  63. # loads a file containing the content of a wx.TreeCtrl
  64. tree = Tree.load(file)
  65. tree.fillCtrl(ctrl)
Reputation Points: 930
Solved Threads: 666
Posting Maven
Gribouillis is offline Offline
2,655 posts
since Jul 2008
Nov 24th, 2008
0

Re: wxTreeCtrl - Load Tree structure from file

I think you could also use XML to save it. If you are using wxPython then there is an XML module you can load that makes it nice and easy to load.

The module is wx.xrc, it can load a panel, a frame or any other kind of object. Its great to have a fiddle with.
Reputation Points: 264
Solved Threads: 183
Veteran Poster
Paul Thompson is offline Offline
1,095 posts
since May 2008
Nov 24th, 2008
0

Re: wxTreeCtrl - Load Tree structure from file

Thanks Gribouillis, but I cant get that code to work at all - some problem with the '@staticmethod'.

Thanks Paul, Ill look that up.

Regards

Max
Reputation Points: 10
Solved Threads: 1
Light Poster
MaxVK is offline Offline
46 posts
since Nov 2008
Nov 25th, 2008
0

Re: wxTreeCtrl - Load Tree structure from file

Sorry, there is a syntax error in the code above. You should replace
python Syntax (Toggle Plain Text)
  1. @staticmethod readCtrl(ctrl):
by
python Syntax (Toggle Plain Text)
  1. @staticmethod
  2. def readCtrl(ctrl):
However, since the code is untested, it's most likely broken, but I think in principle it should store your tree control on the disk and back after you kill a few bugs
Reputation Points: 930
Solved Threads: 666
Posting Maven
Gribouillis is offline Offline
2,655 posts
since Jul 2008
Nov 25th, 2008
0

Re: wxTreeCtrl - Load Tree structure from file

Thanks Gribouillis - I still cant get it to work, but I did find this during my searches:

Quote ...
If you are thinking of pickling/unpickling the wx.TreeCtrl, that won't
work. wxWidgets/wxPython objects are usually non-pickable (with few
exceptions, maybe), and I doubt they will ever be.
I found it here Link so I'm not sure that Pickle is the way to proceed.

I might have to work out how to enumerate the tree accurately and save to an XML file, although that presents challenges of its own!

Paul, I took at look at XRC, but I couldn't see how it would help much (In fact I didn't understand it much at all, beyond the fact that it can be used to separate the design from the code).

Max
Reputation Points: 10
Solved Threads: 1
Light Poster
MaxVK is offline Offline
46 posts
since Nov 2008
Nov 25th, 2008
0

Re: wxTreeCtrl - Load Tree structure from file

I don't quite remember but I believe that treectrl structure can be loaded from a dictionary, right?

If that is correct then you can simply use pickle to store/load the dictionary.. which will save a few lines of code I guess...
Reputation Points: 355
Solved Threads: 292
Veteran Poster
jlm699 is offline Offline
1,102 posts
since Jul 2008
Nov 25th, 2008
0

Re: wxTreeCtrl - Load Tree structure from file

Thanks jlm699, Iv not gotten round to dictionaries yet, but Ill take a look.

Max
Reputation Points: 10
Solved Threads: 1
Light Poster
MaxVK is offline Offline
46 posts
since Nov 2008
Nov 26th, 2008
0

Re: wxTreeCtrl - Load Tree structure from file

Well! Now I know what dictionaries are! However, I'm no closer to loading/saving the structure of a tree, in fact I managed to get my program to crash every time I tried!

I'm having trouble with enumerating the tree correctly and creating the dictionary with the results, and thus far I have failed to create a dictionary with the complete structure.

Having actually produced a dictionary, albeit without the complete tree structure, I managed to save it but I cant reload it into the tree at all.

Can anyone help with this please?

max
Reputation Points: 10
Solved Threads: 1
Light Poster
MaxVK is offline Offline
46 posts
since Nov 2008
Nov 29th, 2008
0

Re: wxTreeCtrl - Load Tree structure from file

Okay, Iv managed to answer this myself, although the method is a bit of a workaround hack!

The code is below, but Ill explain quickly, the file that holds the structure of the tree is in the format:

"Root Item Name#Item Name"

This format, along with the way in which the file is loaded, would allow us to add other items of data to be related to each tree item.

Caveats:
The load routine is designed around the file that was output by the save routine! You can of course code this file by hand if you wish to!

Saving comes first because as the tree is saved it creates the correct file format for re-loading. Firstly I define three variables to hold some data later (These are used by both routines):

python Syntax (Toggle Plain Text)
  1. self.HoldBuffer1 = ""
  2. self.HoldBuffer2 = ""
  3. self.TROG = ""

Now then, lets assume that you have a button "btnSAVE":

python Syntax (Toggle Plain Text)
  1. #
  2. def btnSAVE_OnClick(self, event):
  3. #we can set this to root here because we want to
  4. #start from the first item
  5. self.HoldBuffer1 = "ROOT"
  6. #just as good housekeeping
  7. self.TROG = ""
  8. #call the routine that will build the data to
  9. #save
  10. self.tSaveTree(self.cTREE.GetRootItem())
  11. #save the data
  12. f = open( 'treestructure.dat', 'w')
  13. f.write(self.TROG)
  14. f.close()
  15. event.Skip()
  16.  
  17. #
  18. #
  19. #
  20. #
  21. #
  22. def tSaveTree(self, treeNode):
  23. #as we loop through the tree we add the relevant info
  24. #to TROG
  25. if self.HoldBuffer1 == "ROOT":
  26. self.TROG = self.TROG + "ROOT#" + self.cTREE.GetItemText(treeNode) + "\n"
  27. self.HoldBuffer1 = ""
  28. else:
  29. #because this is not the root item we need to
  30. #find the text of the parent item
  31. x = self.cTREE.GetItemParent(treeNode)
  32. b = self.cTREE.GetItemText(x)
  33. self.TROG = self.TROG + b + "#" + self.cTREE.GetItemText(treeNode) + "\n"
  34.  
  35. if self.cTREE.GetChildrenCount(treeNode, False):
  36. cookie = -1
  37. child, cookie = self.cTREE.GetFirstChild(treeNode)
  38. while child:
  39. self.tSaveTree(child)
  40. child, cookie = self.cTREE.GetNextChild(treeNode, cookie)
  41.  
  42. #

Okay, so now there is a file (called treestructure.dat), and we know what format it is in. So loading becomes fairly easy:

python Syntax (Toggle Plain Text)
  1. #
  2. #
  3. def btnLOAD_OnClick(self, event):
  4. i = 0
  5. f = open( 'treestructure.dat', 'r')
  6. x = f.readline()
  7. #loop for as long as we have something in
  8. #the line
  9. while x > "":
  10. #remove the linefeed at the end of the line
  11. #or things go wrong
  12. #KLeft is my own little function - you can
  13. #use any method you like as long as you
  14. #lose the linefeed!
  15. z = KLeft(x, len(x) - 1)
  16. #split the string
  17. dank = z.split('#')
  18. #if this is the first line we have read
  19. #then we know that it will be the root item
  20. if i == 0:
  21. #this is the root item
  22. troot = self.cTREE.AddRoot(dank[1])
  23. else:
  24. #dank 0 holds the text of the parent item
  25. self.HoldBuffer1 = dank[0]
  26. self.HoldBuffer2 = dank[1]
  27. self.tLoadTree(self.cTREE.GetRootItem())
  28.  
  29. #increment this now for the next item
  30. i = i + 1
  31. #read the next line
  32. x = f.readline()
  33. #all done so close the file
  34. f.close()
  35.  
  36. #
  37. #
  38. #
  39. #
  40. #
  41. def tLoadTree(self, treeNode):
  42. if self.HoldBuffer1 == self.cTREE.GetItemText(treeNode):
  43. self.cTREE.AppendItem(treeNode,self.HoldBuffer2)
  44. return
  45.  
  46. if self.cTREE.GetChildrenCount(treeNode, False):
  47. cookie = -1
  48. child, cookie = self.cTREE.GetFirstChild(treeNode)
  49. while child:
  50. self.tLoadTree(child)
  51. child, cookie = self.cTREE.GetNextChild(treeNode, cookie)
  52. #
  53. #

All done! Like I said, it ain't pretty, but it works.

I would of course be happy for anyone to show me a faster, cleaner way of ending up with the same thing.

Regards

Max
Reputation Points: 10
Solved Threads: 1
Light Poster
MaxVK is offline Offline
46 posts
since Nov 2008

This thread is solved

Either the thread starter or a moderator has marked this thread as solved. You can most likely trust the responses and answers given. There is most likely no reason for any further responses to be posted here. If you have a related question, please start a new thread in this forum instead.

This thread is more than three months old

No one has posted to this discussion for at least three months. Please let old threads die and do not reply to them unless you feel you have something new and valuable to contribute that absolutely must be added to make the discussion complete. Otherwise, please start a new thread in this forum instead.
Message:
Previous Thread in Python Forum Timeline: List operation problem
Next Thread in Python Forum Timeline: Tank simulated game using Class Objects and Lists.





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC