| | |
wxTreeCtrl - Load Tree structure from file
Please support our Python advertiser: Programming Forums - DaniWeb Sister Site
Thread Solved |
•
•
Join Date: Nov 2008
Posts: 41
Reputation:
Solved Threads: 1
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
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
I would suggest something like this, with the pickle module (completely untested)
python Syntax (Toggle Plain Text)
import pickle class Tree(object): # a tree class, with a single root (a Node object) def __init__(self): self.root = None def fillCtrl(self, ctrl): # fills an empty wx.TreeCtrl (ctrl) with the content of the tree structure if self.root is None: return root_item = ctrl.AddRoot(self.root.text) self.root.fillCtrl(ctrl, root_item) def dump(self, file): # writes the tree structure to a file using the pickle protocol pickle.dump(file, self) @staticmethod def load(file): # creates a new Tree which content is read in a file return pickle.load(file) @staticmethod readCtrl(ctrl): # creates a new Tree from the content of a wx.TreeCtrl self = Tree() item = ctrl.GetRootItem() self.root = Node() self.root.text = ctrl.GetItemText(item) self.root.readCtrl(ctrl, item) return self class Node(list): # A class for nodes of Tree objects. Each node is a list which elements are # the subnodes def __init__(self): list.__init__(self) self.text = "" def fillCtrl(self, ctrl, parent_item): # fills a wx.TreeCtrl with items corresponding to the descent of this node for child in self: item = ctrl.AppendItem(parent_item, child.text) child.fillCtrl(ctrl, item) def readCtrl(self, ctrl, item): # creates the descent of this node from the content of a wx.TreeCtrl item child_item = ctrl.GetFirstChild(item) if child_item[0]: child_item = child_item[0] else: return while True: self.append(Node()) self[-1].text = ctrl.GetItemText(child_item) self[-1].readCtrl(ctrl, child_item) child_item = ctrl.GetNextSibling(child_item) if not child_item: break def dumpCtrl(ctrl, file): # Dumps the content of a wx.TreeCtrl to a opened file tree = Tree.readCtrl(ctrl) tree.dump(file) def loadCtrl(ctrl, file): # loads a file containing the content of a wx.TreeCtrl tree = Tree.load(file) tree.fillCtrl(ctrl)
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.
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
Check out my Site | and join us on IRC | Python Specific IRC
Sorry, there is a syntax error in the code above. You should replace
by
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
python Syntax (Toggle Plain Text)
@staticmethod readCtrl(ctrl):
python Syntax (Toggle Plain Text)
@staticmethod def readCtrl(ctrl):
•
•
Join Date: Nov 2008
Posts: 41
Reputation:
Solved Threads: 1
Thanks Gribouillis - I still cant get it to work, but I did find this during my searches:
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
•
•
•
•
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 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
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...
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...
•
•
Join Date: Nov 2008
Posts: 41
Reputation:
Solved Threads: 1
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
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
•
•
Join Date: Nov 2008
Posts: 41
Reputation:
Solved Threads: 1
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):
Now then, lets assume that you have a button "btnSAVE":
Okay, so now there is a file (called treestructure.dat), and we know what format it is in. So loading becomes fairly easy:
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
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)
self.HoldBuffer1 = "" self.HoldBuffer2 = "" self.TROG = ""
Now then, lets assume that you have a button "btnSAVE":
python Syntax (Toggle Plain Text)
# def btnSAVE_OnClick(self, event): #we can set this to root here because we want to #start from the first item self.HoldBuffer1 = "ROOT" #just as good housekeeping self.TROG = "" #call the routine that will build the data to #save self.tSaveTree(self.cTREE.GetRootItem()) #save the data f = open( 'treestructure.dat', 'w') f.write(self.TROG) f.close() event.Skip() # # # # # def tSaveTree(self, treeNode): #as we loop through the tree we add the relevant info #to TROG if self.HoldBuffer1 == "ROOT": self.TROG = self.TROG + "ROOT#" + self.cTREE.GetItemText(treeNode) + "\n" self.HoldBuffer1 = "" else: #because this is not the root item we need to #find the text of the parent item x = self.cTREE.GetItemParent(treeNode) b = self.cTREE.GetItemText(x) self.TROG = self.TROG + b + "#" + self.cTREE.GetItemText(treeNode) + "\n" if self.cTREE.GetChildrenCount(treeNode, False): cookie = -1 child, cookie = self.cTREE.GetFirstChild(treeNode) while child: self.tSaveTree(child) child, cookie = self.cTREE.GetNextChild(treeNode, cookie) #
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)
# # def btnLOAD_OnClick(self, event): i = 0 f = open( 'treestructure.dat', 'r') x = f.readline() #loop for as long as we have something in #the line while x > "": #remove the linefeed at the end of the line #or things go wrong #KLeft is my own little function - you can #use any method you like as long as you #lose the linefeed! z = KLeft(x, len(x) - 1) #split the string dank = z.split('#') #if this is the first line we have read #then we know that it will be the root item if i == 0: #this is the root item troot = self.cTREE.AddRoot(dank[1]) else: #dank 0 holds the text of the parent item self.HoldBuffer1 = dank[0] self.HoldBuffer2 = dank[1] self.tLoadTree(self.cTREE.GetRootItem()) #increment this now for the next item i = i + 1 #read the next line x = f.readline() #all done so close the file f.close() # # # # # def tLoadTree(self, treeNode): if self.HoldBuffer1 == self.cTREE.GetItemText(treeNode): self.cTREE.AppendItem(treeNode,self.HoldBuffer2) return if self.cTREE.GetChildrenCount(treeNode, False): cookie = -1 child, cookie = self.cTREE.GetFirstChild(treeNode) while child: self.tLoadTree(child) child, cookie = self.cTREE.GetNextChild(treeNode, cookie) # #
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
![]() |
Other Threads in the Python Forum
- Previous Thread: List operation problem
- Next Thread: Tank simulated game using Class Objects and Lists.
| Thread Tools | Search this Thread |
address anydbm app bash beginner changecolor cipher class clear conversion coordinates corners curves definedlines development dictionary dynamic events examples excel feet file float format function generator getvalue gui handling homework images import input ip java keycontrol line linux list lists loan loop maintain matching maze millimeter mouse mysqldb number numbers output parsing path port prime programming projects py2exe pygame pymailer python queue random rational raw_input recursion recursive scrolledtext searchingfile shebang singleton slicenotation split string strings table tails terminal text thread threading time tlapse tooltip tuple tutorial type ubuntu unicode url urllib urllib2 valueerror variable variables vigenere web wx.wizard wxpython xlwt






