wxTreeCtrl - Load Tree structure from file

Thread Solved

Join Date: Nov 2008
Posts: 41
Reputation: MaxVK is an unknown quantity at this point 
Solved Threads: 1
MaxVK MaxVK is offline Offline
Light Poster

wxTreeCtrl - Load Tree structure from file

 
0
  #1
Nov 24th, 2008
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
Reply With Quote Quick reply to this message  
Join Date: Jul 2008
Posts: 924
Reputation: Gribouillis is a jewel in the rough Gribouillis is a jewel in the rough Gribouillis is a jewel in the rough 
Solved Threads: 216
Gribouillis's Avatar
Gribouillis Gribouillis is online now Online
Posting Shark

Re: wxTreeCtrl - Load Tree structure from file

 
0
  #2
Nov 24th, 2008
I would suggest something like this, with the pickle module (completely untested)
  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)
Reply With Quote Quick reply to this message  
Join Date: May 2008
Posts: 907
Reputation: Paul Thompson has a spectacular aura about Paul Thompson has a spectacular aura about 
Solved Threads: 145
Sponsor
Paul Thompson's Avatar
Paul Thompson Paul Thompson is offline Offline
previously paulthom12345

Re: wxTreeCtrl - Load Tree structure from file

 
0
  #3
Nov 24th, 2008
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.
Make it idiot proof and someone will make a better idiot.
Check out my Site | and join us on IRC | Python Specific IRC
Reply With Quote Quick reply to this message  
Join Date: Nov 2008
Posts: 41
Reputation: MaxVK is an unknown quantity at this point 
Solved Threads: 1
MaxVK MaxVK is offline Offline
Light Poster

Re: wxTreeCtrl - Load Tree structure from file

 
0
  #4
Nov 24th, 2008
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
Reply With Quote Quick reply to this message  
Join Date: Jul 2008
Posts: 924
Reputation: Gribouillis is a jewel in the rough Gribouillis is a jewel in the rough Gribouillis is a jewel in the rough 
Solved Threads: 216
Gribouillis's Avatar
Gribouillis Gribouillis is online now Online
Posting Shark

Re: wxTreeCtrl - Load Tree structure from file

 
0
  #5
Nov 25th, 2008
Sorry, there is a syntax error in the code above. You should replace
  1. @staticmethod readCtrl(ctrl):
by
  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
Reply With Quote Quick reply to this message  
Join Date: Nov 2008
Posts: 41
Reputation: MaxVK is an unknown quantity at this point 
Solved Threads: 1
MaxVK MaxVK is offline Offline
Light Poster

Re: wxTreeCtrl - Load Tree structure from file

 
0
  #6
Nov 25th, 2008
Thanks Gribouillis - I still cant get it to work, but I did find this during my searches:

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
Reply With Quote Quick reply to this message  
Join Date: Jul 2008
Posts: 1,046
Reputation: jlm699 is a jewel in the rough jlm699 is a jewel in the rough jlm699 is a jewel in the rough jlm699 is a jewel in the rough 
Solved Threads: 264
Sponsor
jlm699's Avatar
jlm699 jlm699 is offline Offline
Knows where his Towel is

Re: wxTreeCtrl - Load Tree structure from file

 
0
  #7
Nov 25th, 2008
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...
1. Use Code Tags.
2. Homework? Show Effort.
3. Keep discussions on the forum: no PMs
Reply With Quote Quick reply to this message  
Join Date: Nov 2008
Posts: 41
Reputation: MaxVK is an unknown quantity at this point 
Solved Threads: 1
MaxVK MaxVK is offline Offline
Light Poster

Re: wxTreeCtrl - Load Tree structure from file

 
0
  #8
Nov 25th, 2008
Thanks jlm699, Iv not gotten round to dictionaries yet, but Ill take a look.

Max
Reply With Quote Quick reply to this message  
Join Date: Nov 2008
Posts: 41
Reputation: MaxVK is an unknown quantity at this point 
Solved Threads: 1
MaxVK MaxVK is offline Offline
Light Poster

Re: wxTreeCtrl - Load Tree structure from file

 
0
  #9
Nov 26th, 2008
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
Reply With Quote Quick reply to this message  
Join Date: Nov 2008
Posts: 41
Reputation: MaxVK is an unknown quantity at this point 
Solved Threads: 1
MaxVK MaxVK is offline Offline
Light Poster

Re: wxTreeCtrl - Load Tree structure from file

 
0
  #10
Nov 29th, 2008
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):

  1. self.HoldBuffer1 = ""
  2. self.HoldBuffer2 = ""
  3. self.TROG = ""

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

  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:

  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
Reply With Quote Quick reply to this message  
Reply

This thread has been marked solved.
Perhaps start a new thread instead?
Message:



Other Threads in the Python Forum
Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC